Перестановки значений в массиве

Предположим, что массив

Array
(
 [0] => 1
 [1] => 2
 [2] => 3
 [3] => 4
)

Я хочу вызвать функцию, предоставив два параметра (оба массива) со следующими перестановками -

array(1) and array(2,3,4)
array(1,2) and array(3,4)
array(1,2,3) and array (4)
array(1,3) and array(2,4)
array(1,4) and array(2,3)
array(2) and array(1,3,4)
and so on...

Конечно, фактические массивы будут больше.

3 ответа

Я не знаю, как называется эта "перестановка" (это, возможно, не перестановка), но мне было перспективно использовать тот факт, что элементы в наборе упорядочены (если нет, то порядок index, поэтому используйте индекс вместо значения), поэтому для перехода справа налево и объединения всех левых с правильными комбинациями.

Это возможно с рекурсией или с стеком, я обычно предпочитаю стек.

Использование, как было предложено (инкапсуляция вызова функции):

$funky = function($a, $b) {
 printf("(%s) and (%s)\n", implode(',', $a), implode(',', $b));
};
$paired = function($function) {
 return function(array $array) use ($function) {
 ...
 };
};
$funkyAll = $paired($funky);
$funkyAll(range(1, 5));

Выполнение этой задачи с помощью стратегии сортировки (более важной для хранения памяти) обеспечивает следующий вывод (отформатирован в столбцах):

(1) and (2,3,4,5) (2,4) and (1,3,5) (1,4,5) and (2,3)
(2) and (1,3,4,5) (2,5) and (1,3,4) (2,3,4) and (1,5)
(3) and (1,2,4,5) (3,4) and (1,2,5) (2,3,5) and (1,4)
(4) and (1,2,3,5) (3,5) and (1,2,4) (2,4,5) and (1,3)
(5) and (1,2,3,4) (4,5) and (1,2,3) (3,4,5) and (1,2)
(1,2) and (3,4,5) (1,2,3) and (4,5) (1,2,3,4) and (5)
(1,3) and (2,4,5) (1,2,4) and (3,5) (1,2,3,5) and (4)
(1,4) and (2,3,5) (1,2,5) and (3,4) (1,2,4,5) and (3)
(1,5) and (2,3,4) (1,3,4) and (2,5) (1,3,4,5) and (2)
(2,3) and (1,4,5) (1,3,5) and (2,4) (2,3,4,5) and (1)

Иллюстративная реализация (полный исходный код как gist) оптимизирована для памяти и создает этот порядок (array_pop вместо array_shift):

(1) and (2,3,4,5) (2,4) and (1,3,5) (1,4,5) and (2,3)
(2) and (1,3,4,5) (2,5) and (1,3,4) (1,3,4) and (2,5)
(3) and (1,2,4,5) (2,4,5) and (1,3) (1,3,5) and (2,4)
(4) and (1,2,3,5) (2,3,4) and (1,5) (1,3,4,5) and (2)
(5) and (1,2,3,4) (2,3,5) and (1,4) (1,2,3) and (4,5)
(4,5) and (1,2,3) (2,3,4,5) and (1) (1,2,4) and (3,5)
(3,4) and (1,2,5) (1,2) and (3,4,5) (1,2,5) and (3,4)
(3,5) and (1,2,4) (1,3) and (2,4,5) (1,2,4,5) and (3)
(3,4,5) and (1,2) (1,4) and (2,3,5) (1,2,3,4) and (5)
(2,3) and (1,4,5) (1,5) and (2,3,4) (1,2,3,5) and (4)

Реализация:

$stack[] = array(array(), $array);
while (list($left, $right) = array_pop($stack)) {
 $min = end($left);
 foreach ($right as $value)
 {
 if ($value < $min) continue;
 $left2 = array_merge($left, array($value));
 $right2 = array_diff($right, $left2);
 if (!($left2 && $count = count($right2))) continue;
 $function($left2, $right2);
 --$count && $stack[] = array($left2, $right2);
 }
}

Надеюсь, это полезно.

Другой алгоритм, связанный с массивом: Сортировка с модулем (только для справки, при написании этого мне напомнили эту матричную вещь)


Я думаю, что это то, что вам нужно.

Код:

Выход:

Array
(
 [0] => A C E
 [1] => A C F
 [2] => A D E
 [3] => A D F
 [4] => B C E
 [5] => B C F
 [6] => B D E
 [7] => B D F
)

Использование: (как в вашем примере)

$combos = combinations(array(array(1,4),array(2,3)));


как насчет использования array_pop с array_merge

chk this url

http://php.net/manual/en/function.array-pop.php

и используйте предложение sarafov с URL

http://www.sonyjose.in/blog/?p=62

что-то вроде

foreach($combinations as $combination)
 while(in_array($combination)){
 $arr = array_pop($combination);
 foo($fruit , $combination); 
 }
}

licensed under cc by-sa 3.0 with attribution.