Perl6:将列表中的元素与另一个列表

时间:2017-03-31 19:06:57

标签: perl6

我有一个数字列表 L 。还有另一个数字列表 M 。我需要返回 L M 中找到的 L' 数字列表。

编辑 :数学上,我正在寻找Multiset路口。

示例:

  

L = 3,1,4,1,5,92,6    M = 9,7,121,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。至少对我的初学者来说:)

3 个答案:

答案 0 :(得分:6)

你可以用袋子做到:

def get_who_likes_sarah():
    names = []
    for m in Man.select(graph):
        try:
            name = m.likes._related_objects[0][0].name
            if name == "Sarah":
                names.append(m.name)
        except:
            pass
    return names

<强>输出:

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;

(如果您不关心重复,请使用套装代替行李。)

答案 1 :(得分:6)

根据您正在寻找的精确语义,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',其各自的值< / em>(重复计数)是整数121

要让Perl 6从包中生成一个列表,每个键重复其关联值指示的次数,请使用.kxxv方法:

.kxxv.put with L.Bag ∩ M.Bag;

显示:

9 1 1 2

kxxv方法的助记符是k表示“密钥”,然后是xx,类似于xx重复运算符,最后是v对于“价值”。如果你考虑它,它就有意义了。)

但也许一包不行。例如,结果中元素的顺序可能很重要 - 您需要9 1 2 1而不是9 1 1 2吗?如果行李不是正确的方法,我会延长这个答案。

答案 2 :(得分:1)

你可以试试这个:

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]