Я хочу сделать перестановку в Perl. Например, у меня есть три массива: ["big", "tiny", "small"]
, а затем у меня есть ["red", "yellow", "green"]
, а также ["apple", "pear", "banana"]
.
Я понимаю, что это называется перестановкой. Но я не уверен, как это сделать. Также я не знаю, сколько массивов я могу иметь. Может быть три или четыре, поэтому я не хочу делать вложенный цикл.
Ответ 2
Мне пришлось решить эту точную проблему несколько лет назад. Я не смог придумать свое решение, но вместо этого столкнулся с этим замечательным фрагментом кода, который включает умное и разумное использование map
наряду с рекурсией:
#!/usr/bin/perl
print "permute:\n";
print "[", join(", ", @$_), "]\n" for permute([1,2,3], [4,5,6], [7,8,9]);
sub permute {
my $last = pop @_;
unless(@_) {
return map([$_], @$last);
}
return map {
my $left = $_;
map([@$left, $_], @$last)
}
permute(@_);
}
Да, это выглядит сумасшедшим, но позвольте мне объяснить! Функция будет возвращаться до тех пор, пока @_
не будет пуст, и в этот момент она вернет ([1], [2], [3])
(список из трех элементов массива) к предыдущему уровню рекурсии. На этом уровне $last
есть ссылка на массив, содержащий [4, 5, 6]
.
Затем тело внешнего отображения выполняется три раза с $_
, установленным на [1]
, затем [2]
и, наконец, [3]
. Затем внутренняя карта выполняется над (4, 5, 6)
для каждой итерации внешнего отображения, и это возвращает ([1, 4], [1, 5], [1, 6])
, ([2, 4], [2, 5], [2, 6])
и, наконец, ([3, 4], [3, 5], [3, 6])
.
Последний, но один рекурсивный вызов возвращает ([1, 4], [1, 5], [1, 6], [2, 4], [2, 5], [2, 6], [3, 4], [3, 5], [3, 6])
.
Затем он запускает этот результат против [7,8,9]
, который дает вам [1, 4, 7], [1, 4, 8], [1, 4, 9], [1, 5, 7], [1, 5, 8], [1, 5, 9], [1, 6, 7], [1, 6, 8], [1, 6, 9], [2, 4, 7], [2, 4, 8], [2, 4, 9], [2, 5, 7], [2, 5, 8], [2, 5, 9], [2, 6, 7], [2, 6, 8], [2, 6, 9], [3, 4, 7], [3, 4, 8], [3, 4, 9], [3, 5, 7], [3, 5, 8], [3, 5, 9], [3, 6, 7], [3, 6, 8], [3, 6, 9]
Я помню, как публиковал вопрос о perlmonks.org, прося кого-нибудь объяснить это мне.
Вы можете легко адаптировать это решение к своей проблеме.