如何按条件拆分列表为两部分?Perl是否有类grep的现成工具函数
Perl中同时获取grep匹配结果与补集的方法
List::Util作为核心自带的列表工具模块,并没有提供可以同时返回匹配结果和补集的函数,不过这类需求已经有非常成熟的现成实现,不需要从零编写复杂逻辑:
- 最方便的方案是直接使用
List::MoreUtils模块提供的part列表分区函数,完全适配需求。该函数会根据传入代码块的返回值,把原列表拆分为多个数组引用;当代码块返回布尔真/假值时,就刚好把列表拆成匹配、不匹配两个部分:
use List::MoreUtils qw(part); my @fruit = qw(apple banana cherry date elderberry); # 筛选长度大于5的元素,同时拿到不符合条件的补集 my ($not_matched, $matched) = part { length($_) > 5 ? 1 : 0 } @fruit; # 解引用后@$matched 为 qw(banana cherry elderberry),@$not_matched为剩余元素
注意part会将代码块的返回值作为分区的索引下标,所以在判断逻辑里显式返回0、1,可以避免匹配集和补集的顺序搞混。
- 如果不想额外安装非核心模块,用原生Perl语法也可以用极精简的代码实现相同效果,运行性能和原生
grep基本持平:
my (@matched, @not_matched); push @{ 写在这里的匹配条件 ? \@matched : \@not_matched }, $_ for @原列表;
比如要筛选列表中带字符a的字符串,写法如下:
my (@matched, @not_matched); push @{ /a/ ? \@matched : \@not_matched }, $_ for qw(apple banana cherry date);
补充说明:List::Util目前内置的grep相关工具,仅包含first(返回第一个匹配的元素)、any/all/none(判断列表是否存在匹配/全匹配/全不匹配)这类布尔判断或单值返回的函数,没有内置分区筛选的能力。
内容的提问来源于stack exchange,提问作者Anna
相关产品推荐
相关产品推荐

