tags:

views:

75

answers:

4

Say i start with a simple array (which could be theoretically of any length):

$ids  = array(1,2,3,4);

What it the best solution for splitting this array into an array of unique pairs like:

$pair[0] = array(1,2);
$pair[1] = array(1,3);
$pair[2] = array(1,4);
$pair[3] = array(2,3);
$pair[4] = array(2,4);
$pair[5] = array(3,4);
A: 

Fixed from my initial jump-the-gun suggestion of array_chunk()

Try this instead:

$ids  = array(1, 2, 3, 4);
$out = array();

while ($item = array_shift($ids)) {
    foreach ($ids as $key=>$value) {
        $out[] = array($item, $value);
    }
}
Nev Stokes
`array_chunk` won't do what the OP wants, look at the example output. OP wants combinations.
Daniel Vandersluis
Ah, silly me. I didn't read the output through properly!
Nev Stokes
A: 

$pair = array_chunk($ids, 2);

http://www.php.net/manual/en/function.array-chunk.php

SpacedMonkey
He's looking for a cartesian product, not splitting the array into smaller chunks...
ircmaxell
reading fail :(
SpacedMonkey
+3  A: 

The simplest solution is to use a nested loop and build combinations as you go, although note that the complexity here is O(n2).

$ids = array(1,2,3,4,4);
$combinations = array();

$ids = array_unique($ids); // remove duplicates
$num_ids = count($ids);

for ($i = 0; $i < $num_ids; $i++)
{
  for ($j = $i+1; $j < $num_ids; $j++)
  {
    $combinations[] = array($ids[$i], $ids[$j]);
  }
}

See this in action at http://www.ideone.com/9wzvP

Daniel Vandersluis
You could get away with the `in_array` check by doing `array_unique` on `$ids`. And you can also speed it up by counting `$ids` as a precondition before the loops (since it's not going to change). I only mention these since you do mention the complexity...
ircmaxell
@ircmaxell True about counting `$ids` first, though that won't affect the complexity. I don't think you can use `array_unique` ahead of time though... it depends on the OP's goal. ie. if `$ids = array(1,2,3,3)`, should [3,3] be a result?
Daniel Vandersluis
I can confirm that 3,3 shouldn't be a result
seengee
@seengee In that case, I've updated my answer.
Daniel Vandersluis
Counting `$ids` won't affect complexity significantly (since it's an `O(1)` function), but `in_array` is not `O(1)` (I'm not positive, but I think it may be `O(n)`, but I may be mistaken), so that would affect complexity. And yes, it does depend on the goal (The OP is not asking for a true cartesian product, but a limited one (and I can't remember the name for it off the top of my head))...
ircmaxell
@ircmaxell I'd think `array_unique` is probably `O(n^2)` as well, no? (See http://stackoverflow.com/questions/478002/php-arrays-remove-duplicates-time-complexity)
Daniel Vandersluis
@ircmaxell you're right that the `in_array` step I had before would have made the solution closer to `O(n^3)` though, because `in_array` is likely a hidden loop that I wasn't considering.
Daniel Vandersluis
+1  A: 

Probably not the best solution

$ids  = array(1,2,3,4);

$pairs = array();
foreach($ids as $key => $data){
    foreach($ids as $subkey => $subdata){
        if( $subkey != $key){
            if(!in_array(array($subdata, $data) , $pairs) ){
                $pairs[] = array($data, $subdata);
            }
        }
    }
}

Anyway it works

armonge