Perl6:将列表中的元素与另一个列表匹配
Perl6: Match elements in a list with another list
我有一个数字列表 L。还有另一个数字列表M。我需要 return 列表 L' both L 和 M.
编辑:从数学上讲,我正在寻找 Multiset 交集。
示例:
L = 3, 1
, 4, 1
, 5, 9
, 2
, 6
M = 9
, 7, 1
, 2
, 1
, 1
L' = 9, 1, 2, 1
我为此写了following code:
my @some-numbers = 3, 1, 4, 1, 5, 9, 2, 6;
my @to-match = 9, 7, 1, 2, 1, 1;
my @matched;
my %histogram;
for @some-numbers -> $n { %histogram{$n}++ };
for @to-match -> $n {
next if not defined %histogram{$n};
if %histogram{$n} > 0 {
push @matched, $n;
%histogram{$n}--;
}
};
say @matched;
虽然达到了目的,但我想知道是否有惯用的 Perl6 方法来做到这一点?
一些背景:我一直在尝试一起学习 Perl6 和 Python,并用两种语言解决相同的难题。 Python针对上述问题给出了一个特别的pleasing solution。至少对于我的初学者来说:)
你可以试试这个:
use v6;
my @some_numbers = 3, 1, 4, 1, 5, 9, 2, 6;
my @to_match = 9, 7, 1, 2, 1, 1;
my %seen = map { $_ => 1 }, @to_match;
my @matched = grep { %seen{$_}:exists }, @some_numbers;
say @matched;
输出:
[1 1 9 2]
你可以用袋子做:
my $some-numbers = bag 3, 1, 4, 1, 5, 9, 2, 6;
my $to-match = bag 9, 7, 1, 2, 1, 1;
my $matched = $some-numbers ∩ $to-match;
say $matched;
输出:
bag(9, 1(2), 2)
您可以使用 .kxxv
将袋子变回数组。
my @match-list = $matched.kxxv;
say @match-list;
输出:
[9 1 1 2]
(如果您不关心重复项,请使用集合而不是包。)
根据您正在寻找的精确语义,Bag 操作可能只是门票:
my \L = 3, 1, 4, 1, 5, 9, 2, 6;
my \M = 9, 7, 1, 2, 1, 1;
.put with L.Bag ∩ M.Bag;
显示:
9 1(2) 2
这是 Bag
的字符串化,包含三个 键 '9'
、'1'
和 '2'
,它们各自值(重复计数)是整数 1
、2
和 1
.
要让 Perl 6 从包中生成一个列表,其中每个键重复其关联值指示的次数,请使用 .kxxv
方法:
.kxxv.put with L.Bag ∩ M.Bag;
显示:
9 1 1 2
(kxxv
方法的助记符是 k
对应 "key" 然后是 xx
类似于 xx
重复运算符,最后是 v
for "value"。如果你仔细想想,这有点道理。)
但也许一个袋子不行。例如,也许结果中元素的顺序很重要——您需要 9 1 2 1
而不是 9 1 1 2
?如果包不是正确的方式,我会扩展这个答案。
我有一个数字列表 L。还有另一个数字列表M。我需要 return 列表 L' both L 和 M.
编辑:从数学上讲,我正在寻找 Multiset 交集。
示例:
L = 3,
1
, 4,1
, 5,9
,2
, 6
M =9
, 7,1
,2
,1
, 1
L' = 9, 1, 2, 1
我为此写了following code:
my @some-numbers = 3, 1, 4, 1, 5, 9, 2, 6;
my @to-match = 9, 7, 1, 2, 1, 1;
my @matched;
my %histogram;
for @some-numbers -> $n { %histogram{$n}++ };
for @to-match -> $n {
next if not defined %histogram{$n};
if %histogram{$n} > 0 {
push @matched, $n;
%histogram{$n}--;
}
};
say @matched;
虽然达到了目的,但我想知道是否有惯用的 Perl6 方法来做到这一点?
一些背景:我一直在尝试一起学习 Perl6 和 Python,并用两种语言解决相同的难题。 Python针对上述问题给出了一个特别的pleasing solution。至少对于我的初学者来说:)
你可以试试这个:
use v6;
my @some_numbers = 3, 1, 4, 1, 5, 9, 2, 6;
my @to_match = 9, 7, 1, 2, 1, 1;
my %seen = map { $_ => 1 }, @to_match;
my @matched = grep { %seen{$_}:exists }, @some_numbers;
say @matched;
输出:
[1 1 9 2]
你可以用袋子做:
my $some-numbers = bag 3, 1, 4, 1, 5, 9, 2, 6;
my $to-match = bag 9, 7, 1, 2, 1, 1;
my $matched = $some-numbers ∩ $to-match;
say $matched;
输出:
bag(9, 1(2), 2)
您可以使用 .kxxv
将袋子变回数组。
my @match-list = $matched.kxxv;
say @match-list;
输出:
[9 1 1 2]
(如果您不关心重复项,请使用集合而不是包。)
根据您正在寻找的精确语义,Bag 操作可能只是门票:
my \L = 3, 1, 4, 1, 5, 9, 2, 6;
my \M = 9, 7, 1, 2, 1, 1;
.put with L.Bag ∩ M.Bag;
显示:
9 1(2) 2
这是 Bag
的字符串化,包含三个 键 '9'
、'1'
和 '2'
,它们各自值(重复计数)是整数 1
、2
和 1
.
要让 Perl 6 从包中生成一个列表,其中每个键重复其关联值指示的次数,请使用 .kxxv
方法:
.kxxv.put with L.Bag ∩ M.Bag;
显示:
9 1 1 2
(kxxv
方法的助记符是 k
对应 "key" 然后是 xx
类似于 xx
重复运算符,最后是 v
for "value"。如果你仔细想想,这有点道理。)
但也许一个袋子不行。例如,也许结果中元素的顺序很重要——您需要 9 1 2 1
而不是 9 1 1 2
?如果包不是正确的方式,我会扩展这个答案。