带有 $_ 的 Perl 多顺序 grep
Perl multi-order grep with $_
我正在努力学习 Perl 的 grep
。
我想查询散列的哪些键在数组中不是
my %args = ( fake => 1);
my @defined_args = ('color', 'colors', 'data', 'figheight', 'figwidth', 'filename', 'flip', 'grid', 'labelsize', 'logscale', 'minor_gridlines');
my @bad_args = grep { not grep {$_} @defined_args} keys %args;
where the list of bad args is in @bad_args
最后一行显然是错误的。
我知道我可以用散列做同样的事情,但我希望能够用多顺序 grep 做到这一点,即 grep on grep。
我怎样才能像下面那样做到这一点?
my @bad_args = grep { not grep {$_ eq $_} @defined_args} keys %args;
我很困惑,因为会有两个 $_
,我不能 运行 对其进行相等性测试。
首先是直接答案 -- grep
占用的那个块,您可以在其中放入任何代码。这就是块的要点,以及基于 returns.
最后一个语句的真实性的元素 passes/not
my @bad_args = grep {
my $key = $_;
@defined_args == grep { $key ne $_ } @defined_args
} keys %args;
这里我们测试一个键是否不等于数组元素,然后测试它是否不等于所有元素,由什么决定。另一种方法是测试它是否等于任何一个元素,
not grep { $key eq $_ } @defined_args;
这有点复杂,需要用否定来处理。
但这些都是常见的事情,而且有图书馆。
在上面直接改进
use List::Util 1.33 qw(none); # before 1.33 it was in List::MoreUtils
my @bad_args = grep {
my $key = $_;
none { $key eq $_ } @defined_args
} keys %args;
现在,所需的“否定”已包含在库的函数名称中,使其更易于查看。此外,none
将在发现失败后停止,而 grep
始终处理所有元素,因此这也更有效率。
与基于散列的方法(复杂度 O(NM-M2/2) 或所以)但这与小型阵列完全无关。问题中提到的使用散列来处理与存在相关的问题是一种标准;例如参见 [=20=]).
最后,虽然问题是关于(双重)过滤的,但应该提到我们正在寻找列表中的哪些元素不在另一个列表中;列表之间的“差异”。然后其他类型的库开始发挥作用。一些例子
use Set::Scalar;
...
my $keys = Set::Scalar->new(keys %args);
my $good = Set::Scalar->new(@defined_args);
my $keys_not_in_good = $keys->difference($good);
say $keys_not_in_good;
另请注意Set::Object在同一个营地。
还有专门用于数组比较的工具,比如List::Compare
use List::Compare;
...
my $lc = List::Compare->new('-u', '-a', \@defined_args, [keys %args]);
my @only_in_second = $lc->get_complement();
say "@only_in_second";
选项 -u
和 -a
展示了一些模块功能,以加快速度;他们不是必需的。这个模块有很多,看文档。
另一端是简单的 Array::Utils.
还有更多。例如,请参阅 this page 以获得大量想法。
当您陷入这些纠结时,有时最好找到不同的方法。
有两件事需要考虑。如果你想嵌套使用 $_
,你需要以某种方式保护外部的。由于要在同一个表达式中使用外层和内层,其中一个需要不同的名称:
grep {
my $top = $_;
my $count = grep { $top eq $_ } ...;
...
} keys %args;
但是,内部 grep 有点奇怪。你想检查列表中是否有某物。这就是散列和 exists
:
的工作
my %allowed_args = map { $_, 1 } @allowed_args;
my @found_bad_args = grep { ! exists $allowed_args{$_} } keys %args;
我正在努力学习 Perl 的 grep
。
我想查询散列的哪些键在数组中不是
my %args = ( fake => 1);
my @defined_args = ('color', 'colors', 'data', 'figheight', 'figwidth', 'filename', 'flip', 'grid', 'labelsize', 'logscale', 'minor_gridlines');
my @bad_args = grep { not grep {$_} @defined_args} keys %args;
where the list of bad args is in @bad_args
最后一行显然是错误的。
我知道我可以用散列做同样的事情,但我希望能够用多顺序 grep 做到这一点,即 grep on grep。
我怎样才能像下面那样做到这一点?
my @bad_args = grep { not grep {$_ eq $_} @defined_args} keys %args;
我很困惑,因为会有两个 $_
,我不能 运行 对其进行相等性测试。
首先是直接答案 -- grep
占用的那个块,您可以在其中放入任何代码。这就是块的要点,以及基于 returns.
my @bad_args = grep {
my $key = $_;
@defined_args == grep { $key ne $_ } @defined_args
} keys %args;
这里我们测试一个键是否不等于数组元素,然后测试它是否不等于所有元素,由什么决定。另一种方法是测试它是否等于任何一个元素,
not grep { $key eq $_ } @defined_args;
这有点复杂,需要用否定来处理。
但这些都是常见的事情,而且有图书馆。
在上面直接改进
use List::Util 1.33 qw(none); # before 1.33 it was in List::MoreUtils
my @bad_args = grep {
my $key = $_;
none { $key eq $_ } @defined_args
} keys %args;
现在,所需的“否定”已包含在库的函数名称中,使其更易于查看。此外,none
将在发现失败后停止,而 grep
始终处理所有元素,因此这也更有效率。
与基于散列的方法(复杂度 O(NM-M2/2) 或所以)但这与小型阵列完全无关。问题中提到的使用散列来处理与存在相关的问题是一种标准;例如参见 [=20=]).
最后,虽然问题是关于(双重)过滤的,但应该提到我们正在寻找列表中的哪些元素不在另一个列表中;列表之间的“差异”。然后其他类型的库开始发挥作用。一些例子
use Set::Scalar;
...
my $keys = Set::Scalar->new(keys %args);
my $good = Set::Scalar->new(@defined_args);
my $keys_not_in_good = $keys->difference($good);
say $keys_not_in_good;
另请注意Set::Object在同一个营地。
还有专门用于数组比较的工具,比如List::Compare
use List::Compare;
...
my $lc = List::Compare->new('-u', '-a', \@defined_args, [keys %args]);
my @only_in_second = $lc->get_complement();
say "@only_in_second";
选项 -u
和 -a
展示了一些模块功能,以加快速度;他们不是必需的。这个模块有很多,看文档。
另一端是简单的 Array::Utils.
还有更多。例如,请参阅 this page 以获得大量想法。
当您陷入这些纠结时,有时最好找到不同的方法。
有两件事需要考虑。如果你想嵌套使用 $_
,你需要以某种方式保护外部的。由于要在同一个表达式中使用外层和内层,其中一个需要不同的名称:
grep {
my $top = $_;
my $count = grep { $top eq $_ } ...;
...
} keys %args;
但是,内部 grep 有点奇怪。你想检查列表中是否有某物。这就是散列和 exists
:
my %allowed_args = map { $_, 1 } @allowed_args;
my @found_bad_args = grep { ! exists $allowed_args{$_} } keys %args;