
stukerr
Tengo una matriz de PHP que se parece a este ejemplo:
$array[0][0] = 'apples';
$array[0][1] = 'pears';
$array[0][2] = 'oranges';
$array[1][0] = 'steve';
$array[1][1] = 'bob';
Y me gustaría poder producir a partir de esto una tabla con todas las combinaciones posibles de estos, pero sin repetir ninguna combinación (independientemente de su posición), así que, por ejemplo, esto generaría
Array 0 Array 1
apples steve
apples bob
pears steve
pears bob
Pero me gustaría que esto pudiera funcionar con tantas matrices diferentes como sea posible.

usuario187291
esto se llama “producto cartesiano”, página de manual de php en matrices http://php.net/manual/en/ref.array.php muestra algunas implementaciones (en comentarios).
y aquí hay otro más:
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);
Está buscando el producto cartesiano de las matrices, y hay un ejemplo en el sitio de matrices php: http://php.net/manual/en/ref.array.php
Syom copió http://www.php.net/manual/en/ref.array.php#54979 pero lo adapté esto para convertirlo en una versión asociativa:
function array_cartesian($arrays) {
$result = array();
$keys = array_keys($arrays);
$reverse_keys = array_reverse($keys);
$size = intval(count($arrays) > 0);
foreach ($arrays as $array) {
$size *= count($array);
}
for ($i = 0; $i < $size; $i ++) {
$result[$i] = array();
foreach ($keys as $j) {
$result[$i][$j] = current($arrays[$j]);
}
foreach ($reverse_keys as $j) {
if (next($arrays[$j])) {
break;
}
elseif (isset ($arrays[$j])) {
reset($arrays[$j]);
}
}
}
return $result;
}
Necesitaba hacer lo mismo y probé las soluciones anteriores publicadas aquí, pero no pude hacer que funcionaran. Tengo 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 combinaciones no repetitivas. 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')
);
Luego imprimirá algo como esto:
Increíble – beneficio – Maravilloso
Increíble – oferta – Maravilloso
Increíble – recompensa – Maravilloso
Maravilloso – beneficio – Increíble
Maravilloso – oferta – Increíble
Maravilloso – recompensa – Increíble
foreach($parentArray as $value) {
foreach($subArray as $value2) {
$comboArray[] = array($value, $value2);
}
}
no me juzgues..

usuario187291
Creo que esto funciona, 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 la mala denominación de las 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;
}
}
}
}
@usuario187291
Modifiqué esto para que 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 tanto, devuelve esa matriz vacía tan importante (el mismo resultado que ninguna combinación) cuando pasa 0 argumentos.
Solo noté esto porque lo estoy usando como
$combos = call_user_func_array('array_cartesian', $array_of_arrays);
¿Habrá Array 2, Array 3, Array N? ¿O solo dos matrices?
– Luz plateada
25 de marzo de 2010 a las 15:05
Hola, lo siento por no ser más claro, podría haber una matriz 2, una matriz 3 hasta una matriz n. Gracias.
– stukerr
25 de marzo de 2010 a las 15:05
Lo que necesita es una unión cruzada fácil en SQL, pero necesita pensar un poco en PHP
– Luz plateada
25 de marzo de 2010 a las 15:15
Da la casualidad de que esto proviene de una base de datos mySQL, todas las opciones (manzanas, peras, naranjas, steve, bob, etc.) están en un kit de tabla, una clave para otra tabla que define en qué grupo están (frutas, personas, etc.). ), ¿alguna idea de cómo podría trabajar eso en mysql?
– stukerr
25 de marzo de 2010 a las 15:20