【问题标题】:Perl - determine if an array is a subset of another array [duplicate]Perl - 确定一个数组是否是另一个数组的子集
【发布时间】:2013-06-01 14:18:46
【问题描述】:

我有以下代码。如果没有附加的 CPAN 模块,isSubset 可以写得更简单吗?

my @possibleNames = ("adam", "chelsea");
my @actualNames = ("adam", "chucky", "chelsea");

sub isSubset {
    my ($littleSet, $bigSet) = @_;
    foreach (@{$littleSet}) {
        return 0 unless ($_ ~~ @{$bigSet});
    }
    return 1;
}

printf("%s\n", (isSubset(\@possibleNames, \@actualNames) ? "yes" : "no"));

【问题讨论】:

  • 只是use Array::Utils。没有理由不能使用 CPAN 中的模块。
  • my ($sub, super) = @_; $_ ~~ $super or return 0 for @$sub; 1,但这只是化妆品。如果集合很大,或者如果您反复测试一组,最好使用散列:$_ ~~ $super 变为 exists $super->{$_}。不过,仅适用于字符串。
  • 如果您不想将模块拉下来,请获取源代码并在应有的地方使用它。
  • 智能匹配 perl 运算符现在在 perl 5.18 中是实验性的,因此您会在此环境中收到警告。

标签: perl


【解决方案1】:

一种相当有效的方法是:

sub isSubset {
    my ($littleSet, $bigSet) = @_;
    my %hash;
    undef @hash{@$littleSet};  # add a hash key for each element of @$littleSet
    delete @hash{@$bigSet};    # remove all keys for elements of @$bigSet
    return !%hash;             # return false if any keys are left in the hash
}

【讨论】:

  • 优秀的微型解决方案!谢谢!
  • 我不会使用 undef。
  • @RicardoGemignani: undef @hash{@keys} 将散列片 @hash{@keys} 中每个键的值设置为 undef。 (是的,undef 可以接受参数列表!有关更多详细信息,请参阅perldoc -f undef。)鉴于我们并不真正关心什么值,这是一种将所有这些键添加到散列的快速且节省内存的方法他们有;比$hash{$_} = 1 for @keys 更有效率。
  • 在切片上使用 undef 没有记录为有效(尽管它确实有效)。最好做@hash{@$littleSet} = ();
  • @ysth:奇怪的是,你似乎是对的。我可以发誓至少在官方 perldocs 中隐含地提到了它,但我现在找不到它。虽然delete 被明确记录在切片上工作,但undef 不是。我觉得这可能是文档中的一个错误,因为它是自 Perl 5 早期以来一直有效的常用习惯用法。
【解决方案2】:
my @possibleNames = ("adam", "chelsea");
my @actualNames = ("adam", "chucky", "chelsea");

my $is_subset = 0==grep !defined, map { @$_{@actualNames}=(1)x@actualNames; delete @$_{@possibleNames} } {};

但说真的,请使用 Array::Utils::array_minus。

【讨论】:

  • 能否请您对此解决方案添加一些解释?它看起来很酷,但很难理解那里发生了什么。
猜你喜欢
  • 2012-08-29
  • 2010-09-24
  • 1970-01-01
  • 1970-01-01
  • 2012-05-20
  • 2020-03-10
  • 2022-06-11
  • 1970-01-01
  • 2016-12-13
相关资源
最近更新 更多