2011-12-19 40 views
26

Estoy tratando de encontrar todas las combinaciones de elementos en varias matrices. El número de matrices es aleatorio (puede ser 2, 3, 4, 5 ...). El número de elementos en cada matriz es al azar también ...Cómo generar en PHP todas las combinaciones de elementos en matrices múltiples

Para exemple, tengo los 3 arrays:

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

quisiera generar una matriz con 3 x 3 x 2 = 18 combinaciones :

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

El problema es crear una función con un número variable de matrices de origen ...

+1

Uno siempre quiere un elemento de * * cada matriz? – goat

Respuesta

43

Aquí está la solución recursiva:

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

¿cómo debo cambiar esta función si quiero las combinaciones únicas para las matrices duplicadas? Por ejemplo, si tengo una matriz ('A1', 'A2', 'A3'), una matriz ('A1', 'A2', 'A3'), una matriz ('C1', 'C2') y quiero como resultado "A1, A2, C1", "A1, A3, C1", etc., pero NO "A1, A1, C1"? Además (si no estoy pidiendo demasiado;), {"A1", "A2", "C1"} es lo mismo que {"A2", "A1", "C1"}, ¿así que solo quiero una combinación? –

+0

@AlexAngelico - y para cualquier persona con la misma pregunta, vea array_unique, http://php.net/manual/en/function.array-unique.php –

13

Este es un producto cartesiano, y acabo de asked the same question not too long ago. Aquí está el 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

El enlace al sitio web PHP aparentemente no lleva nada sobre esta función . ¿Podría dar un ejemplo de invocación? – JohnK

+0

Esta función toma más de 2.5 veces más tiempo que la función de Lolo para procesar la misma matriz. –

2

Este código además de la simplicidad, obtiene todas las combinaciones de múltiples matrices y conserva las claves.

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

Ejemplo:

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

volveremos: el

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

No tengo idea de por qué alguien más votó negativamente esto. Esta solución funcionó perfectamente para mí y guardé las teclas de matriz como yo quería. +1 – Eric

2

Sé que esta pregunta es viejo, pero tengo el mismo problema hoy y decidió dar a la nueva Generador una prueba:

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

Resultado:

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

Cuando el pedido no importa, es una combinación. Cuando el pedido importa, es una Permutación. En este caso, es una Permutación y no una Combinación. –

Cuestiones relacionadas