PHP 2D Array выводит все комбинации
У меня была проблема сгибать мой разум некоторое время (голова холодная тоже не помогает!), в основном у меня есть PHP-массив, который выглядит следующим образом:
$array[0][0] = 'apples';
$array[0][1] = 'pears';
$array[0][2] = 'oranges';
$array[1][0] = 'steve';
$array[1][1] = 'bob';
И я хотел бы иметь возможность создавать из этой таблицы всю возможную комбинацию из них, но без повторения каких-либо комбинаций (независимо от их положения), поэтому, например, это выводит
Array 0 Array 1
apples steve
apples bob
pears steve
pears bob
Но я хотел бы, чтобы это могло работать с максимально возможным количеством различных массивов.
Ответы
Ответ 1
это называется "декартовым произведением", страницей php man на массивах http://php.net/manual/en/ref.array.php показывает некоторые реализации (в комментариях).
и здесь еще один:
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);
Ответ 2
Вы ищете декартово произведение массивов, и там пример на сайте php массивов: http://php.net/manual/en/ref.array.php
Ответ 3
Syom скопировал http://www.php.net/manual/en/ref.array.php#54979, но я адаптировал его, чтобы стать ассоциативной версией:
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;
}
Ответ 4
Мне нужно было сделать то же самое, и я попробовал предыдущие решения, размещенные здесь, но не смог заставить их работать. Я получил образец от этого умного парня http://www.php.net/manual/en/ref.array.php#54979. Тем не менее, его образец не справился с концепцией отсутствия повторяющихся комбинаций. Поэтому я включил эту часть. Вот моя модифицированная версия, надеюсь, что это поможет:
$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;
}
Результат будет примерно таким:
яблоки - steve
яблоки - bob
груши - steve
груши - боб
апельсины - steve
апельсины - bob
Если массив данных выглядит примерно так:
$data = array(
array('Amazing', 'Wonderful'),
array('benefit', 'offer', 'reward'),
array('Amazing', 'Wonderful')
);
Затем он напечатает что-то вроде этого:
Удивительно - полезно - Замечательно
Удивительно - предложение - Замечательно
Удивительный - награда - Замечательный
Чудесный - выгода - Удивительный
Замечательный - предложение - Удивительный
Чудесный - награда - Удивительный
Ответ 5
Это работает, я думаю - хотя после его написания я понял, что он очень похож на то, что другие положили, но он дает вам массив в запрошенном формате. Извините за наименьшее имя переменной.
$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;
}
}
}
}
Ответ 6
@user187291
Я изменил это как
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;
}
поэтому он возвращает этот важный массив (тот же результат, что и никакие комбинации), когда вы передаете 0 аргументов.
Только заметил это, потому что я использую его как
$combos = call_user_func_array('array_cartesian', $array_of_arrays);
Ответ 7
foreach($parentArray as $value) {
foreach($subArray as $value2) {
$comboArray[] = array($value, $value2);
}
}
Не судите меня.
Ответ 8
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;
}
Ответ 9
Мне пришлось составлять комбинации из вариантов продукта. Это решение использует рекурсию и работает с 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";
}
Ответ 10
Элегантная реализация на основе собственной функции 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;
}
Ответ 11
В базе данных MySQL это будет так:
SELECT *
FROM `options`, `groups`
Что все:)