3

I have a PHP array that has from 2-5 items in it.

$z=["itema", "itemb", "itemc", "itemd","iteme"];

I need to have a way to go through the array and match each item against each other one time. So the output would look like

itema vs itemb
itema vs itemc
itema vs itemd
itema vs iteme

itemb vs itemc
itemb vs itemd
itemb vs iteme

itemc vs itemd...ect 

I can not seem to get the loop to hit every item. I think it has to be a loop in a loop since my just one loop doesn't work.

And it has to go to each only once. I am so lost on how to get this to work. Any help would be much appreciated.

1
  • Please provide the code that you have so far - it will help users to pinpoint possible problems with your solution. Also describe how exactly the code fails to achieve your goal. Commented Nov 16, 2015 at 18:43

4 Answers 4

6

You could use two for loops

$count = count($z);
for ($i = 0; $i < $count - 1; $i++) {
    for ($j = $i + 1; $j < $count; $j++) {
        // compare $z[$i] with $z[$j]...
    }
}

The other loop goes from 0 to n - 2 and the inner loop takes the value from the outer value as initial and goes to the end.


If you also need to handle associative arrays, like one commenter mentioned, you could use array_values (and array_keys) to handle this case.

$values = array_values($z);
$keys = array_keys($z); // optional - only used, if you need the keys..
$count = count($values);
for ($i = 0; $i < $count - 1; $i++) {
    for ($j = $i + 1; $j < $count; $j++) {
        // compare $values[$i] with $values[$j]...
        // or $keys[$i] with $keys[$j];
    }
}

Note: A foreach loop won't work in either case, because you can't told the inner loop to skip all values, already seen in the outher loop. And teaching the foreach loop this behavior would result in a foreach, that effectly looks like a simple for loop and is slower. There's simply no benefit in using a foreach.

Sign up to request clarification or add additional context in comments.

10 Comments

Thats it ! than you very much. I figured I needed an inner loop but I could not get it right.
@Philipp congrats on 10k
I down voted it because this approach doesn't work with string key array's. It's better to use foreach instead of for, please see this approach: stackoverflow.com/questions/33741890/…
@Julian - 1. assoc arrays wasn't the authors problem. 2. The "better" approach is not what the author wants, as this compares [1,2] and also [2,1]. If you can't use numeric indices, you could first apply array_values to $z and if you also need the key, there is more to done. But just using a foreach doesn't work!
@Philipp You are right about array_values() but it's wrong to say that a foreach won't work. Please see here: stackoverflow.com/questions/33741890/…
|
0

Not tested but something like:

foreach($z as $item){
  foreach($z as $item2){
    if($item!=$item2){
      echo $item . ' vs ' . $item2;
    }
  }
}

Comments

0
<?php 
$z=["itema", "itemb", "itemc", "itemd","iteme"];

$sizeZ=count($z);
for ($i = 0; $i < $sizeZ-1; $i++) 
{
    for ($j = $i+1; $j < $sizeZ; $j++) 
    {
        echo $z[$i]." vs ".$z[$j]."<br>";
    }
}
?>

Output :

itema vs itemb
itema vs itemc
itema vs itemd
itema vs iteme
itemb vs itemc
itemb vs itemd
itemb vs iteme
itemc vs itemd
itemc vs iteme
itemd vs iteme

Comments

0

In my opinion it's better to use a foreach() then a for().

The approach with the foreach() looks cleaner to me. The approach with the for() is not wrong, but it's strange.

See the example with a foreach:

$z = array('xxApple' => "itema", 'B' => "itemb", 'C' => "itemc", 'D' => "itemd", 'AAAA' => "iteme");
//$z = array("itema", "itemb", "itemc", "itemd", "iteme"); // works also with this array

$x = array_values($z);
$y = array_keys($z); // Optional
foreach($x as $key1 => $item){
  foreach($x as $key2 => $item2){

    if($key2 <= $key1){
        continue;
    }

    if($item == $item2){
        continue;
    }

    echo $item . ' vs ' . $item2 . '<br>';
    // echo $y[$key1] . ' vs ' . $y[$key2] . '<br>'; // Optional
  }
}


//OUTPUT
itema vs itemb
itema vs itemc
itema vs itemd
itema vs iteme
itemb vs itemc
itemb vs itemd
itemb vs iteme
itemc vs itemd
itemc vs iteme
itemd vs iteme

Here are the benchmark results:

Benchmark #1

$z = range(0,20000);

$start = time();
$values = array_values($z);
for ($i = 0; $i < count($values) - 1; $i++) {
    for ($j = $i + 1; $j < count($values); $j++) {
    }
}
$end = time();                  
$elapsedTimeA = $end - $start;

// Case A, elapsed time in seconds: 275
echo 'Case A, elapsed time in seconds: ' . $elapsedTimeA; 


$start = time();
$x = array_values($z);
foreach($x as $key1 => $item){
  foreach($x as $key2 => $item2){

    if($key2 <= $key1){
        continue;
    }

    if($item == $item2){
        continue;
    }
  }
}
$end = time();                   
$elapsedTimeB = $end - $start;

// Case B, elapsed time in seconds: 103
echo 'Case B, elapsed time in seconds: ' . $elapsedTimeB; 

Benchmark #2

$z = range(0,20000);

$start = time();
$values = array_values($z);
$count = count($values);
for ($i = 0; $i < $count - 1; $i++) {
    for ($j = $i + 1; $j < $count; $j++) {
    }
}

$end = time();                  
$elapsedTimeA = $end - $start;

// Case A, elapsed time in seconds: 17
echo 'Case A, elapsed time in seconds: ' . $elapsedTimeA;


$start = time();
$x = array_values($z);
foreach($x as $key1 => $item){
  foreach($x as $key2 => $item2){

    if($key2 <= $key1){
        continue;
    }

    if($item == $item2){
        continue;
    }
  }
}
$end = time();                   
$elapsedTimeB = $end - $start;

// Case B, elapsed time in seconds: 103
echo 'Case B, elapsed time in seconds: ' . $elapsedTimeB; 

1 Comment

Why the big difference in case A? Also, what hardware is the benchmark running on?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.