2011-12-19 16 views
26

Sto tentando di trovare tutte le combinazioni di elementi in diversi array. Il numero di matrici è casuale (può essere 2, 3, 4, 5 ...). Il numero di elementi in ogni matrice è casuale troppo ...Come generare in PHP tutte le combinazioni di elementi in più array

Per exemple, ho le matrici 3:

$arrayA = array('A1','A2','A3'); 
$arrayB = array('B1','B2','B3'); 
$arrayC = array('C1','C2'); 

desidero generare un array di 3 x 3 x 2 = 18 combinazioni :

  • A1, B1, C1
  • A1, B1, C2
  • A1, B2, C1
  • A1, B2, C2
  • A1, B3, C1
  • A1, B3, C2
  • A2, B1, C1
  • A2, B1, C2 ...

Il problema è quello di creare una funzione con un numero variabile di array sorgente ...

+1

Si vuole sempre un elemento da * ogni * array? – goat

risposta

43

Ecco soluzione ricorsiva:

function combinations($arrays, $i = 0) { 
    if (!isset($arrays[$i])) { 
     return array(); 
    } 
    if ($i == count($arrays) - 1) { 
     return $arrays[$i]; 
    } 

    // get combinations from subsequent arrays 
    $tmp = combinations($arrays, $i + 1); 

    $result = array(); 

    // concat each array from tmp with each element from $arrays[$i] 
    foreach ($arrays[$i] as $v) { 
     foreach ($tmp as $t) { 
      $result[] = is_array($t) ? 
       array_merge(array($v), $t) : 
       array($v, $t); 
     } 
    } 

    return $result; 
} 

print_r(
    combinations(
     array(
      array('A1','A2','A3'), 
      array('B1','B2','B3'), 
      array('C1','C2') 
     ) 
    ) 
); 
+0

come dovrei cambiare questa funzione se voglio le combinazioni univoche per gli array duplicati? Ad esempio, se ho array ('A1', 'A2', 'A3'), array ('A1', 'A2', 'A3'), array ('C1', 'C2') e voglio come risultato "A1, A2, C1", "A1, A3, C1", ecc., ma NO "A1, A1, C1"? Inoltre (se non sto chiedendo troppo;), {"A1", "A2", "C1"} è lo stesso che {"A2", "A1", "C1"} quindi voglio solo 1 combinazione? –

+0

@AlexAngelico - e per chiunque altro con la stessa domanda, vedere array_unique, http://php.net/manual/en/function.array-unique.php –

13

Questo è un prodotto cartesiano e ho solo asked the same question not too long ago. Ecco lo algorithm that is posted on the PHP website.

function array_cartesian_product($arrays) 
{ 
    $result = array(); 
    $arrays = array_values($arrays); 
    $sizeIn = sizeof($arrays); 
    $size = $sizeIn > 0 ? 1 : 0; 
    foreach ($arrays as $array) 
     $size = $size * sizeof($array); 
    for ($i = 0; $i < $size; $i ++) 
    { 
     $result[$i] = array(); 
     for ($j = 0; $j < $sizeIn; $j ++) 
      array_push($result[$i], current($arrays[$j])); 
     for ($j = ($sizeIn -1); $j >= 0; $j --) 
     { 
      if (next($arrays[$j])) 
       break; 
      elseif (isset ($arrays[$j])) 
       reset($arrays[$j]); 
     } 
    } 
    return $result; 
} 
+0

Il collegamento al sito Web di PHP non sembra portare nulla a questa funzione . Potresti fare un esempio di invocarlo? – JohnK

+0

Questa funzione richiede più di 2,5 volte la funzione di Lolo per elaborare lo stesso array. –

2

Questo codice oltre alla semplicità, ottiene tutte le combinazioni di più array e conserva le chiavi.

function get_combinations($arrays) { 
    $result = array(array()); 
    foreach ($arrays as $property => $property_values) { 
     $tmp = array(); 
     foreach ($result as $result_item) { 
      foreach ($property_values as $property_key => $property_value) { 
       $tmp[] = $result_item + array($property_key => $property_value); 
      } 
     } 
     $result = $tmp; 
    } 
    return $result; 
} 

Esempio:

Array 
(
    Array 
    (
     '1' => 'White', 
     '2' => 'Green', 
     '3' => 'Blue' 
    ), 
    Array 
    (
     '4' =>' Small', 
     '5' => 'Big' 
    ) 
) 

tornerà:

Array 
(
    [0] => Array 
    (
     [1] => White 
     [4] => Small 
    ) 
    [1] => Array 
    (
     [1] => White 
     [5] => Big 
    ) 
    [2] => Array 
    (
     [2] => Green 
     [4] => Small 
    ) 
    [3] => Array 
    (
     [2] => Green 
     [5] => Big 
    ) 
    [4] => Array 
    (
     [3] => Blue 
     [4] => Small 
    ) 
    [5] => Array 
    (
     [3] => Blue 
     [5] => Big 
    ) 
) 
+0

Non ho idea del motivo per cui qualcun altro ha downvoted questo. Questa soluzione ha funzionato perfettamente per me e ha conservato le chiavi di array come volevo. +1 – Eric

2

So che questa domanda è vecchio, ma ho avuto lo stesso problema di oggi e ha deciso di dare al nuovo Una prova del generatore:

function generateCombinations(array $array) { 
    foreach (array_pop($array) as $value) { 
     if (count($array)) { 
      foreach (generateCombinations($array) as $combination) { 
       yield array_merge([$value], $combination); 
      }; 
     } else { 
      yield [$value]; 
     } 
    } 
} 

foreach (generateCombinations(['a' => ['A'], 'b' => ['B'], 'c' => ['C', 'D'], 'd' => ['E', 'F', 'G']]) as $c) { 
     var_dump($c); 
    } 

Risultato:

array(4) { 
[0]=> 
string(1) "E" 
[1]=> 
string(1) "C" 
[2]=> 
string(1) "B" 
[3]=> 
string(1) "A" 
} 
array(4) { 
[0]=> 
string(1) "E" 
[1]=> 
string(1) "D" 
[2]=> 
string(1) "B" 
[3]=> 
string(1) "A" 
} 
array(4) { 
[0]=> 
string(1) "F" 
[1]=> 
string(1) "C" 
[2]=> 
string(1) "B" 
[3]=> 
string(1) "A" 
} 
array(4) { 
[0]=> 
string(1) "F" 
[1]=> 
string(1) "D" 
[2]=> 
string(1) "B" 
[3]=> 
string(1) "A" 
} 
array(4) { 
[0]=> 
string(1) "G" 
[1]=> 
string(1) "C" 
[2]=> 
string(1) "B" 
[3]=> 
string(1) "A" 
} 
array(4) { 
[0]=> 
string(1) "G" 
[1]=> 
string(1) "D" 
[2]=> 
string(1) "B" 
[3]=> 
string(1) "A" 
} 
+0

Quando l'ordine non è importante, è una combinazione. Quando l'ordine conta è una permutazione. In questo caso, è una permutazione e non una combinazione. –

Problemi correlati