2010-03-25 20 views
19

que he tenido este problema doblando mi mente desde hace un tiempo (la cabeza fría no ayuda, ya sea!), Básicamente tengo una matriz PHP que se parece a este ejemplo:salida de matriz PHP 2D todas las combinaciones

$array[0][0] = 'apples'; 
$array[0][1] = 'pears'; 
$array[0][2] = 'oranges'; 

$array[1][0] = 'steve'; 
$array[1][1] = 'bob'; 

Y me gustaría ser capaz de producir de esta una tabla con todas las combinaciones posibles de estos, pero sin repetir ninguna combinación (independientemente de su posición), así que por ejemplo este emitiría

Array 0   Array 1 
apples    steve 
apples    bob 
pears    steve 
pears    bob 

pero lo haría gustaría que esto sea posible trabajar con tantas matrices diferentes como sea posible le.

+0

Habrá Matriz 2, 3 matriz, matriz de N? ¿O solo dos matrices? –

+0

Hola, lo siento por no aclarar, podría haber una matriz 2, una matriz 3 hasta la matriz n. Gracias. – stukerr

+0

Lo que necesita es una combinación cruzada fácil en SQL, pero necesita algo de reflexión en PHP –

Respuesta

20

esto se llama "producto cartesiano", la página del hombre php en las matrices http://php.net/manual/en/ref.array.php muestra algunas implementaciones (en comentarios).

y aquí está todavía otra:

function array_cartesian() { 
    $_ = func_get_args(); 
    if(count($_) == 0) 
     return array(array()); 
    $a = array_shift($_); 
    $c = call_user_func_array(__FUNCTION__, $_); 
    $r = array(); 
    foreach($a as $v) 
     foreach($c as $p) 
      $r[] = array_merge(array($v), $p); 
    return $r; 
} 

$cross = array_cartesian(
    array('apples', 'pears', 'oranges'), 
    array('steve', 'bob') 
); 

print_r($cross); 
+0

Cosas geniales, justo lo que necesitaba. Muchas gracias – stukerr

+0

vamos a poner la página real allí: http://php.net/manual/en/ref.array.php :) –

+1

Si esta función vive en una clase, es posible que desee cambiar la llamada user_func como así: ' $ c = call_user_func_array (array ($ this, __ FUNCTION__), $ _); '. Además, puede dar una advertencia (no una matriz) si las matrices de entrada no son del mismo tamaño. – Nanne

-2

En la base de datos MySQL en sería así:

SELECT * 
FROM `options`, `groups` 

Eso es todo :)

1

Esto funciona creo que - aunque después de escribirlo Me di cuenta de que es bastante similar a lo que otros han puesto, pero te da una matriz en el formato solicitado. Perdón por los pobres nombres variables.

$output = array(); 
combinations($array, $output); 
print_r($output); 

function combinations ($array, & $output, $index = 0, $p = array()) { 
    foreach ($array[$index] as $i => $name) { 
     $copy = $p; 
     $copy[] = $name; 
     $subIndex = $index + 1; 
     if (isset($array[$subIndex])) { 
      combinations ($array, $output, $subIndex, $copy); 
     } else { 
      foreach ($copy as $index => $name) { 
       if (!isset($output[$index])) { 
        $output[$index] = array(); 
       } 
       $output[$index][] = $name; 
      } 
     } 
    } 
} 
1

@ user187291

he modificado que esto sea

function array_cartesian() { 
    $_ = func_get_args(); 
    if (count($_) == 0) 
     return array(); 
    $a = array_shift($_); 
    if (count($_) == 0) 
     $c = array(array()); 
    else 
     $c = call_user_func_array(__FUNCTION__, $_); 
    $r = array(); 
    foreach($a as $v) 
     foreach($c as $p) 
      $r[] = array_merge(array($v), $p); 
    return $r; 
} 

por lo que devuelve esa importantísima matriz vacía (el mismo resultado que no hay combinaciones) cuando pases 0 argumentos.

Sólo di cuenta de esto, porque lo estoy usando como

$combos = call_user_func_array('array_cartesian', $array_of_arrays); 
1
foreach($parentArray as $value) { 
    foreach($subArray as $value2) { 
     $comboArray[] = array($value, $value2); 
    } 
} 

No me juzgues ...

+0

"Por supuesto, debe funcionar cuando sizeof ($ array)> = 2." –

0
function array_comb($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; 
} 
2

Tenía que hacer lo mismo y probé las soluciones anteriores publicadas aquí pero no pude hacer que funcionen. Obtuve una muestra de este tipo inteligente http://www.php.net/manual/en/ref.array.php#54979. Sin embargo, su muestra no manejó el concepto de ninguna combinación repetitiva. Así que incluí esa parte.Aquí está mi versión modificada, espero que ayude:

$data = array(
     array('apples', 'pears', 'oranges'), 
     array('steve', 'bob') 
    ); 

    $res_matrix = $this->array_cartesian_product($data); 

    foreach ($res_matrix as $res_array) 
    { 
     foreach ($res_array as $res) 
     { 
      echo $res . " - "; 
     } 
     echo "<br/>"; 
    } 


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); 
    $res_index = 0; 
    for ($i = 0; $i < $size; $i++) 
    { 
     $is_duplicate = false; 
     $curr_values = array(); 
     for ($j = 0; $j < $sizeIn; $j++) 
     { 
      $curr = current($arrays[$j]); 
      if (!in_array($curr, $curr_values)) 
      { 
       array_push($curr_values , $curr); 
      } 
      else 
      { 
       $is_duplicate = true; 
       break; 
      } 
     } 
     if (!$is_duplicate) 
     { 
      $result[ $res_index ] = $curr_values; 
      $res_index++; 
     } 
     for ($j = ($sizeIn -1); $j >= 0; $j--) 
     { 
      $next = next($arrays[ $j ]); 
      if ($next) 
      { 
       break; 
      } 
      elseif (isset ($arrays[ $j ])) 
      { 
       reset($arrays[ $j ]); 
      } 
     } 
    } 
    return $result; 
} 

el resultado sería algo como esto:
manzanas - steve
manzanas - bob
peras - Steve
peras - Bob
naranjas - Steve
naranjas - bob

Si la matriz de datos es algo como esto:

$data = array(
     array('Amazing', 'Wonderful'), 
     array('benefit', 'offer', 'reward'), 
     array('Amazing', 'Wonderful') 
    ); 

entonces será imprimir algo como esto:

increíble - beneficio - maravilloso
increíble - oferta - maravilloso
increíble - recompensa - maravilloso
maravilloso - beneficio - Amazing
maravillosa - oferta - Increíble
Maravillosa - recompensa - Increíble

0

Tuve que hacer combinaciones de las opciones del producto. Esta solución utiliza la recursividad y trabaja con matriz 2D:

function options_combinations($options) { 
    $result = array(); 
    if (count($options) <= 1) { 
     $option = array_shift($options); 
     foreach ($option as $value) { 
      $result[] = array($value); 
     } 
    } else { 
     $option = array_shift($options); 
     $next_option = options_combinations($options); 
     foreach ($next_option as $next_value) { 
      foreach ($option as $value) { 
       $result[] = array_merge($next_value, array($value)); 
      } 
     } 
    } 
    return $result; 
} 

$options = [[1,2],[3,4,5],[6,7,8,9]]; 
$c = options_combinations($options); 
foreach ($c as $combination) { 
    echo implode(' ', $combination)."\n"; 
} 
0

aplicación elegante basado en la función nativa de Python itertools.product

function direct_product(array ...$arrays) 
{ 
    $result = [[]]; 
    foreach ($arrays as $array) { 
     $tmp = []; 
     foreach ($result as $x) { 
      foreach ($array as $y) { 
       $tmp[] = array_merge($x, [$y]); 
      } 
     } 
     $result = $tmp; 
    } 
    return $result; 
} 
Cuestiones relacionadas