We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you two Citrix podcasts. Learn about 2020 trends and get answers to your biggest Citrix questions!Listen Now

x

Using array_unique with foreach

EMB01
EMB01 asked
on
Medium Priority
433 Views
Last Modified: 2012-05-06
I have a code that simply displays an array. I tried adding the first line (attached) so that no duplicates would be echoed. It didn't work. Can someone tell me how to do this? Thank you.
$matches = array_unique($matches);
  foreach($matches[0] as $match){
    echo $match ."</br>";

Open in new window

Comment
Watch Question

Commented:

$matches = array_unique($matches);
  foreach($matches as $match){
    echo $match ."</br>";
  }

Open in new window

Commented:
array_unique doesn't work quite well for multi dim. arrays

Author

Commented:
I tried that already, but it only echoes:
Array

Array

Array

Array

Array

Array

Array

Array

Array

Author

Commented:
What can I use, then, to filter out duplicates?

Commented:
type

print_r($matches) before the array_unique and show me a snippet of it.

Author

Commented:
The array comes from a preg_match_all function so it only displays emails like:
email@email.com
email@email.com
email@email.com

Commented:
I want to see it from the point of view of print_r()

type this

echo "<pre>";
print_r($matches);
echo "</pre>";
 
COPY AND PASTE THE RESULTS.

Open in new window

Author

Commented:
Array
(
    [0] => Array
        (
            [0] => email@email.com
            [1] => email@email.com
            [2] => email@email.com
        )

)

Commented:
Try this.


for ($x=0; $x<count($matches);$x++) {
   $matches[$x] = array_unique($matches[$x]);
}
foreach($matches[0] as $match){
   echo $match ."</br>";
}

Open in new window

Commented:
If that doesn't work,

Does it need to be a multi dim array? or can it be singular?

Author

Commented:
No, that doesn't work, either. I believe it has to be multidim, but I'm not sure... Like I said, it comes from preg_match_all, so whatever is required there is necessary; I have no concern otherwise.

I looked this up:
http://stackoverflow.com/questions/307674/how-to-remove-duplicate-values-from-a-multi-dimensional-array-in-php

Could you see if you could adapt this to my code? I'm not familiar with serialization.

Commented:
that's similar to the way I was going to show you if it didn't need to be  a multi. If it can a singular array then this is way more easy.
$newMatches = array();
 
foreach ($matches['0'] as $match) {
   $newMatches[] = $match;
}
 
$newMatches = array_unique($newMatches);
 
if you want to keep it a multi dim array then
 
 
 
function multi_unique($array) {
        foreach ($array as $k=>$na)
            $new[$k] = serialize($na);
        $uniq = array_unique($new);
        foreach($uniq as $k=>$ser)
            $new1[$k] = unserialize($ser);
        return ($new1);
}
 
$matches = multi_unique($matches);

Open in new window

Author

Commented:
I am confused by everything past line 12. Maybe I can up the points and you can try to break it down for me, later. First, to understand the one dimensional unique array... How do I echo the results of the array? From $newMatches?

Commented:
those were two different examples, to get unique arrays with the multi or if you don't need a multi, how to convert it to a singular then remove the duplicates


foreach ($matches['0'] as $match) {
  echo = $match."<br />";
}

Author

Commented:
The most recently provided code doesn't work. Nothing is displayed even with error reporting turned on.

Commented:
show me what you got.

Author

Commented:
// pregmatch function
foreach ($matches['0'] as $match) {
  echo = $match."<br />";
}

Commented:
I meant the whole thing.

Author

Commented:
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
foreach ($matches['0'] as $match) {
  echo = $match."<br />";
}

Author

Commented:
Where $content = "My name is John Doe and my email address is john@doe.net. My name is John Doe and my email address is johndoe@johndoe.net.";

Commented:
take out the = sing after echo.

Commented:
I accidentally typed it in.

Author

Commented:
Lol, duh! I should have noticed that myself.

Author

Commented:
That code still displays duplicates. What about the new matches part?

Commented:

function multi_unique($array) {
        foreach ($array as $k=>$na)
            $new[$k] = serialize($na);
        $uniq = array_unique($new);
        foreach($uniq as $k=>$ser)
            $new1[$k] = unserialize($ser);
        return ($new1);
}
 
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
 
$matches = multi_unique($matches);
 
foreach ($matches['0'] as $match) {
  echo = $match."<br />";
}

Open in new window

Author

Commented:
I am still get a blank page with no errors.

Commented:
I did it again. wit the = sign.
function multi_unique($array) {
        foreach ($array as $k=>$na)
            $new[$k] = serialize($na);
        $uniq = array_unique($new);
        foreach($uniq as $k=>$ser)
            $new1[$k] = unserialize($ser);
        return ($new1);
}
 
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
 
$matches = multi_unique($matches);
 
foreach ($matches['0'] as $match) {
  echo $match."<br />";
}

Open in new window

Author

Commented:
And, I didn't catch it, again! Still there are duplicates. Here's a print_r:
Array
(
    [0] => Array
        (
            [0] => email@email.com
            [1] => email@email.com
            [2] => email@email.com
        )

)

Commented:
and you copied and pasted directly?

Author

Commented:
Yes, did you try the code yourself?

Commented:
Yeah, nevermind that function doesn't quite do what you want rid of duplicate sets of arrays.

The first one I showed you works for me.
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
 
  for ($x=0;$x<count($matches);$x++) {
	$matches[$x] = array_unique($matches[$x]);
  }
 
  foreach ($matches['0'] as $match) {
        echo $match."<br />";
  }
 
}

Open in new window

Author

Commented:
Let me clarify my code a bit. Because, this still doesn't work for me. Notice how $content changes; I guess that's what makes this a multidimensional array.
<?php
 
for ($counter = 1; $counter < 10; $counter++) {
 
$content = "";
 
// get new content values from text file
 
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
 
  for ($x=0;$x<count($matches);$x++) {
	$matches[$x] = array_unique($matches[$x]);
  }
 
  foreach ($matches['0'] as $match) {
        echo $match."<br />";
  }
 
} else { 
echo "No matches found.";
}
}
 
?>

Open in new window

Commented:
where is $content getting it's value?

Author

Commented:
From a text file like fopen ("myfile.txt", etc...)

Commented:
What I meant was, from what I see $content = ""; when does it get value?

Author

Commented:
It goes:

$content= "";

while( !feof( $fp ) ) {
   
       $buffer = trim( fgets( $fp, 4096 ) );
       $content .= $buffer;
       
    }

You know?

Commented:
when it shows the multiple emails of the same email, goto view source and copy and paste exactly what it looks like.

Author

Commented:
Source of the web page? That's,
email@email.com<br />email@email.com<br />email@email.com<br />

Commented:
If this doesn't work, then I don't know, because the script I gave you works for me, and I don't see anything wrong.
<?php
 
for ($counter = 1; $counter < 10; $counter++) {
 
$content = "";
 
// get new content values from text file
 
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
 
  for ($x=0;$x<count($matches);$x++) {
        for ($y=0;$y<=count($matches[$x]);$y++) {
            if (array_search($matches[$x][$y], $matches[$x])!== false) {
               unset($matches[$x][$y]);
             }
        }
  }
 
  foreach ($matches['0'] as $match) {
        echo $match."<br />";
  }
 
} else { 
echo "No matches found.";
}
}
 
?>

Open in new window

Author

Commented:
I actually not sure what that did... anyway. Thanks for your help... Do I delete this since there is no solution? Sorry to waste your time.

Commented:
did it make any change?

Commented:
where were you putting the print_r()?

Author

Commented:
Yeah, I'm not sure what change it made as there are less results than were before; but I still see this from print_r (which I put at line 18 from the most recent snippet #23684172):
Array ( [0] => Array ( [2] => email@email.com ) )
Array ( [0] => Array ( [2] => email@email.com ) )

Now that I'm looking at it, it seems it still writes the duplicates but it just references a single array. For example, it may regularly have been:
Array ( [0] => Array ( [2] => Info3@shelbysites.com ) )
Array ( [0] => Array ( [21] => Info3@shelbysites.com ) )

But, now it's:
Array ( [0] => Array ( [2] => Info3@shelbysites.com ) )
Array ( [0] => Array ( [2] => Info3@shelbysites.com ) )

Both aren't so useful to me!

Commented:
I see what's happening, it's because of your initial loop for $counter;

we are dealling with many arrays

so print_r() is being called several times.

you need to get it out of the loop

Try this and show me the result. And post  a large chunk.
<?php
$matches = array(); 
for ($counter = 1; $counter < 10; $counter++) {
 
$content = "";
 
// get new content values from text file
 
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
  $found = true;
} else { 
  if ($found != true) {
    $found = false;
  }
}
}
 if ($found == true) {
   print_r($matches);
 } else {
   echo "No matches found.";
}
?>

Open in new window

Author

Commented:
This is all I get:
Array ( [0] => Array ( [0] => email@email.com [1] => email@email.com [2] => email@email.com ) )

Commented:
Perfect!

Now do it like this.

<?php
$matches = array(); 
for ($counter = 1; $counter < 10; $counter++) {
 
$content = "";
 
// get new content values from text file
 
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
  $found = true;
} else { 
  if ($found != true) {
    $found = false;
  }
}
}
 if ($found == true) {
  for ($x=0;$x<count($matches);$x++) {
        $matches[$x] = array_unique($matches[$x]);
  }
 
  foreach ($matches['0'] as $match) {
        echo $match."<br />";
  }
 } else {
   echo "No matches found.";
}
?>

Open in new window

Author

Commented:
I would love to tell you that worked; but, if a .txt file has the following:
email@email.com
Email@email.com
email@Email.com
moreemail@email.com
Moreemail@email.com
moreemail@Email.com

The script seems to only echo the first three (case sensatively):
email@email.com
Email@email.com
email@Email.com

Commented:
So how was it when you were pasting the results they were always lower case?

Well know that I know that try this.


<?php
function in_iarray($str, $a){
  foreach($a as $v){
    if(strcasecmp($str, $v)==0){return true;}
  }
  return false;
}
 
function array_iunique($a){
  $n = array();
  foreach($a as $k=>$v){
    if(!in_iarray($v, $n)){$n[$k]=$v;}
  }
  return $n;
}
 
$matches = array(); 
for ($counter = 1; $counter < 10; $counter++) {
 
$content = "";
 
// get new content values from text file
 
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
  $found = true;
} else { 
  if ($found != true) {
    $found = false;
  }
}
}
 if ($found == true) {
  for ($x=0;$x<count($matches);$x++) {
        $matches[$x] = array_iunique($matches[$x]);
  }
 
  foreach ($matches['0'] as $match) {
        echo $match."<br />";
  }
 } else {
   echo "No matches found.";
}
?>

Open in new window

Author

Commented:
Sorry, I didn't know it mattered. The script only echos the last result; i.e. if this would usually get echoed (with duplicates):
email@email.com
email@email.com
email@email.com
Email@email.com
Email@email.com
moreemail@email.com
moreemail@email.com

Only the last result, "moreemail@email.com," gets echoed.

Author

Commented:
Let me bump this up to 500; it's getting juicy!

Commented:

<?php
function in_iarray($str, $a){
  foreach($a as $v){
    if(strcasecmp($str, $v)==0){return true;}
  }
  return false;
}
 
function array_iunique($a){
  $n = array();
  foreach($a as $k=>$v){
    if(!in_iarray($v, $n)){$n[$k]=$v;}
  }
  return $n;
}
 
$matches = array();
$finalMatches = array(); 
for ($counter = 1; $counter < 10; $counter++) {
 
$content = "";
 
// get new content values from text file
 
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
  $found = true;
  $finalMatches[] = $matches
} else { 
  if ($found != true) {
    $found = false;
  }
}
}
 if ($found == true) {
  for ($x=0;$x<count($finalMatches);$x++) {
        $finalMatches[$x] = array_iunique($finalMatches[$x]);
  }
 
  foreach ($finalMatches['0'] as $finalMatches) {
        echo $finalMatches."<br />";
  }
 } else {
   echo "No matches found.";
}
?>

Open in new window

Author

Commented:
Script produces blank page with no errors.

Commented:

<?php
function in_iarray($str, $a){
  foreach($a as $v){
    if(strcasecmp($str, $v)==0){return true;}
  }
  return false;
}
 
function array_iunique($a){
  $n = array();
  foreach($a as $k=>$v){
    if(!in_iarray($v, $n)){$n[$k]=$v;}
  }
  return $n;
}
 
$matches = array();
$finalMatches = array(); 
for ($counter = 1; $counter < 10; $counter++) {
 
$content = "";
 
// get new content values from text file
 
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
  $found = true;
  $finalMatches[] = $matches
} else { 
  if ($found != true) {
    $found = false;
  }
}
}
 if ($found == true) {
  print_r($finalMatches);
/*
  for ($x=0;$x<count($finalMatches);$x++) {
        $finalMatches[$x] = array_iunique($finalMatches[$x]);
  }
 
  foreach ($finalMatches['0'] as $finalMatches) {
        echo $finalMatches."<br />";
  }
*/
 } else {
   echo "No matches found.";
}
?>

Open in new window

Author

Commented:
Script still produces nothing.

Commented:
there was a missing   ;
<?php
function in_iarray($str, $a){
  foreach($a as $v){
    if(strcasecmp($str, $v)==0){return true;}
  }
  return false;
}
 
function array_iunique($a){
  $n = array();
  foreach($a as $k=>$v){
    if(!in_iarray($v, $n)){$n[$k]=$v;}
  }
  return $n;
}
 
$matches = array();
$finalMatches = array(); 
for ($counter = 1; $counter < 10; $counter++) {
 
$content = "";
 
// get new content values from text file
 
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
  $found = true;
  $finalMatches[] = $matches;
} else { 
  if ($found != true) {
    $found = false;
  }
}
}
 if ($found == true) {
  for ($x=0;$x<count($finalMatches);$x++) {
        $finalMatches[$x] = array_iunique($finalMatches[$x]);
  }
 
  foreach ($finalMatches['0'] as $finalMatches) {
        echo $finalMatches."<br />";
  }
 } else {
   echo "No matches found.";
}
?>

Open in new window

Author

Commented:
So, now it just says, "Array." When I put a print_r on line 38, there still seems to be duplicates. Here's what happens with the added print_r:
Array ( [0] => Array ( [0] => Array ( [0] => email@email.com [1] => email@email.com ) ) [1] => Array ( [0] => Array ( [0] => moreemail@email.com [1] => moreemail@email.com ) ) ) Array

Commented:
ok for this section of code I want you to do this, and copy and paste EXACTLY what you see.
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
  $found = true;
  echo "This is the Matches";
  echo "<pre>";
  print_r($matches);
  echo "</pre>";
  echo "This is the end<br />";
} else { 
  if ($found != true) {
    $found = false;
  }
}

Open in new window

Author

Commented:
This is the Matches
Array
(
    [0] => Array
        (
            [0] => email@email.com
            [1] => email@email.com
        )

)
This is the end
This is the Matches
Array
(
    [0] => Array
        (
            [0] => moreemail@email.com
            [1] => moreemail@email.com
        )

)
This is the end
Array ( )
Notice: Undefined index: 0 in /var/www/vhosts/...  on line 123

Warning: Invalid argument supplied for foreach() in /var/www/vhosts/... on line 123

Commented:
I'm have to leave now, but I will continue helping tomorrow.

Author

Commented:
Okay, I'm looking forward to it! Thanks for your help so far.
Commented:
try this.
<?php
function in_iarray($str, $a){
  foreach($a as $v){
    if(strcasecmp($str, $v)==0){return true;}
  }
  return false;
}
 
function array_iunique($a){
  $n = array();
  foreach($a as $k=>$v){
    if(!in_iarray($v, $n)){$n[$k]=$v;}
  }
  return $n;
}
 
$matches = array();
$finalMatches = array(); 
for ($counter = 1; $counter < 10; $counter++) {
 
$content = "";
 
// get new content values from text file
 
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
  $found = true;
  for ($x=0;$x<count($matches);$x++) {
     $finalMatches[] = $matches[$x];
  }
} else { 
  if ($found != true) {
    $found = false;
  }
}
}
 if ($found == true) {
  foreach ($finalMatches as $finalMatches) {
        echo $finalMatches."<br />";
  }
 } else {
   echo "No matches found.";
}
?>

Open in new window

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

Author

Commented:
It just says,
Array
Array
Array
Array
Array
Array
Array
Array
Array
Commented:
Hey, I think I solved this. See the attached code and let me know what you think.

The code doesn't show any duplicates and it's pretty fast. I'll still throw you all the points I can.
$duplicates = array();
for ($counter = 0; $counter < 10; $counter++) {
 
// get new content values from text file
 
if (preg_match_all('/[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|int|pro|asia|cat|coop|jobs|travel)\b/i', $content, $matches)) {
  foreach ($matches['0'] as $match) {
		if (!in_array($match,$duplicates)) echo $match."<br />";
		$duplicates[] = $match;
  }
 } else {
   echo "No matches found. "."<br />";
}
}

Open in new window

Author

Commented:
I don't want to close this, I want to accept my answer and award points to the expert...

Author

Commented:
Oh! I didn't see the assisted solution. Thanks for your help, modus.
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.