2011-12-19 10 views
26

Próbuję znaleźć wszystkie kombinacje przedmiotów w kilku tablicach. Liczba tablic jest losowa (może to być 2, 3, 4, 5 ...). Liczba elementów w każdej tablicy jest przypadkowy za ...Jak wygenerować w PHP wszystkie kombinacje elementów w wielu tablicach

reprezentują np, mam 3 tablic:

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

chciałbym generowanie tablicy 3 x 3 x 2 = 18 kombinacji :

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

Problemem jest stworzenie funkcją o zmiennej liczbie tablic źródłowych ...

+1

Zawsze chcesz jeden element z każdego * * tablicy? – goat

Odpowiedz

43

Oto rekurencyjny rozwiązanie:

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

Jak mam zmienić tę funkcję, jeśli chcę unikatowe kombinacje dla zduplikowanych tablic? Na przykład, jeśli mam tablicę ("A1", "A2", "A3"), tablicę ("A1", "A2", "A3"), tablicę ("C1", "C2") i chcę jako wynik "A1, A2, C1", "A1, A3, C1", itp., ale NIE "A1, A1, C1"? Również (jeśli nie pytam za dużo;), {"A1", "A2", "C1"} to jest to samo, co {"A2", "A1", "C1"}, więc chcę tylko 1 kombinację? –

+0

@AlexAngelico - i dla każdego, kto ma to samo pytanie, zobacz: array_unique, http://php.net/manual/en/function.array-unique.php –

13

To jest produkt kartezjański, a ja po prostu asked the same question not too long ago. Oto 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

Link do strony PHP najwyraźniej nie ma nic wspólnego z tą funkcją . Czy możesz podać przykład wywołania go? – JohnK

+0

Ta funkcja zajmuje 2,5 razy więcej czasu niż funkcja Lolo do przetwarzania tej samej tablicy. –

2

Kod ten oprócz prostoty, uzyskać wszystkie kombinacje wielu tablic i przechowuje klucze.

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; 
} 

Exemple:

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

Wrócimy:

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

Nie mam pojęcia, dlaczego ktoś inny to zajął. To rozwiązanie sprawdziło się doskonale i zachowałem klucze tablicy, tak jak tego chciałem. +1 – Eric

2

Wiem, że to pytanie jest stary, ale mam ten sam problem dzisiaj i postanowiliśmy dać nowy Próba generatora:

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); 
    } 

Wynik:

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

Gdy zamówienie nie ma znaczenia, jest to kombinacja. Gdy zamówienie ma znaczenie, jest to permutacja. W tym przypadku jest to permutacja, a nie kombinacja. –

Powiązane problemy