Почему Math :: Cartesian :: Продукт возвращает благословенные объекты?

StackOverflow https://stackoverflow.com/questions/4428705

  •  09-10-2019
  •  | 
  •  

Вопрос

Я заметил Математика :: Cartesian :: Продукт Возвращает массив благословенных объектов вместо простого массива массивов. Я не мог понять, почему. Мне на самом деле нужно сделать дополнительную работу (безразлым), чтобы использовать результаты ...

Это было полезно?

Решение

Одна альтернатива - это модуль Set :: CrossProduct, что даст обычные, безграничные массивные ссылки:

use Set::CrossProduct;
my $iter = Set::CrossProduct->new([ \@foo, \@bar ]);

while (my $tuple = $iter->get){
    ...
}

Или получить все кортежи сразу:

my @tuples = $iter->combinations;

Другие советы

Я добавил А. cartesian функция к Список :: Быт недавно:

  • cartesian CODE LIST_of_ARRAYREF

    cartesian Вычисляет декартовому продукту любого количества массивов Refs, каждый из которых может быть любым размером. Возвращает генератор

    use List::Gen 'cartesian';
    my $product = cartesian {$_[0] . $_[1]} [qw/a b/], [1, 2];
    print "@$product"; # 'a1 a2 b1 b2'
    

Возвращенный «Генератор» - это ленивый массив, который будет генерировать значения, когда их задают. Есть также итеративные и другие методы доступа:

my $pairs = cartesian {@_} [qw/$ @ %/], ['a'..'z'], [1 .. 3];

while (my @tuple = $pairs->next) {  # $pairs->reset; #$pairs->index = 5; ...
    print @tuple, ', ';
}
# $a1, $a2, $a3, $b1, $b2, $b3, $c1, $c2, $c3, $d1, $d2, $d3, $e1 ...

Я не знаю, насколько большой наборы вы будете работать, но это преимущество в использовании вышеуказанного подхода заключается в том, что требования к хранению для генератора остаются O(1)

my $digits = cartesian {join '' => @_} ([0..9]) x 10;

say for @$digits[10**9 - 3 .. 10**9 + 3];

#   0999999998
#   0999999999
#   1000000000
#   1000000001
#   1000000002
#   1000000003

который рассчитывает только 6 элементов набора, и ничего не хранит.

Как вы можете видеть из примеров, возвращаемое значение cartesian сам является объектом генератора, но последующие возвратные значения объекта - это то, к чему проходило кодер cartesian Возвращает. Поэтому, если вы хотите, чтобы массивные ссылки, это так же просто, как: cartesian {\@_} ...


Кроме того, какая дополнительная работа вы должны были иметь дело с благословенной ссылкой? Пресвященный массив все еще является массивом в любом смысле, кроме чего ref вернется. Если вы пишете логику переключения на основе типа ссылочного типа, Scalar::UtilС. reftype это то, что вы должны использовать.

Это благословляет массивы, возвращаемые cartesian так что, когда какой-то код как следующий

$b = $cartesian $a1, $a2;
$c = $cartesian $b, $a3;

... это может обнаружить, что $b является результатом предыдущего вызова модулю.

Делать декартовой операции продукта - это что-то тривиальное, если данные, которые возвращаются этим модулем, не соответствуют вашим потребностям, подумайте о том, чтобы списать операцию самостоятельно с нуля.

В любом случае, проверка исходного кода модуля показывает, что он не слишком велик.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top