Max*_*xVT 20 arrays perl list find
我有一个可能的值列表:
@a = qw(foo bar baz);
Run Code Online (Sandbox Code Playgroud)
如何以简明的方式检查值$val是否存在@a?
一个明显的实现是遍历列表,但我确信TMTOWTDI.
感谢所有回答的人!我想强调的三个答案是:
接受的答案 - 最"内置"和向后兼容的方式.
RET的答案是最干净的,但只适用于Perl 5.10及更高版本.
draegtun的答案(可能)有点快,但需要使用额外的模块.我不喜欢添加依赖项,如果我可以避免它们,在这种情况下不需要性能差异,但如果你有一个1,000,000元素的列表,你可能想尝试这个答案.
Che*_*oft 20
Perl在grep()函数中的优势就是为此而设计的.
@matches = grep( /^MyItem$/, @someArray );
Run Code Online (Sandbox Code Playgroud)
或者您可以将任何表达式插入匹配器
@matches = grep( $_ == $val, @a );
Run Code Online (Sandbox Code Playgroud)
bri*_*foy 18
这在perlfaq4的答案中得到了回答:"如何判断某个元素是否包含在列表或数组中?" .
要搜索perlfaq,您可以使用自己喜欢的浏览器在perlfaq中搜索所有问题的列表.
从命令行,您可以使用-q开关来perldoc搜索关键字.您可以通过搜索"列表"找到您的答案:
perldoc -q list
Run Code Online (Sandbox Code Playgroud)
(这个答案的部分内容由Anno Siegel和brian d foy提供)
听到"in"这个词表示你可能应该使用散列而不是列表或数组来存储数据.哈希旨在快速有效地回答这个问题.数组不是.
话虽如此,有几种方法可以解决这个问题.在Perl 5.10及更高版本中,您可以使用智能匹配运算符来检查项目是否包含在数组或哈希中:
use 5.010;
if( $item ~~ @array )
{
say "The array contains $item"
}
if( $item ~~ %hash )
{
say "The hash contains $item"
}
Run Code Online (Sandbox Code Playgroud)
使用早期版本的Perl,您需要做更多的工作.如果要在任意字符串值上多次进行此查询,最快的方法可能是反转原始数组并维护一个哈希,其键是第一个数组的值:
@blues = qw/azure cerulean teal turquoise lapis-lazuli/;
%is_blue = ();
for (@blues) { $is_blue{$_} = 1 }
Run Code Online (Sandbox Code Playgroud)
现在你可以检查$ is_blue {$ some_color}.首先将蓝调全部放在哈希中可能是个好主意.
如果值都是小整数,则可以使用简单的索引数组.这种阵列占用的空间更少:
@primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31);
@is_tiny_prime = ();
for (@primes) { $is_tiny_prime[$_] = 1 }
# or simply @istiny_prime[@primes] = (1) x @primes;
Run Code Online (Sandbox Code Playgroud)
现在你检查$ is_tiny_prime [$ some_number].
如果有问题的值是整数而不是字符串,则可以使用位字符串来节省相当多的空间:
@articles = ( 1..10, 150..2000, 2017 );
undef $read;
for (@articles) { vec($read,$_,1) = 1 }
Run Code Online (Sandbox Code Playgroud)
现在检查一些$ n的vec($ read,$ n,1)是否为真.
这些方法保证了快速的单独测试,但需要重新组织原始列表或数组.如果必须针对同一阵列测试多个值,它们只会得到回报.
如果您只测试一次,标准模块List :: Util会首先导出该功能.它一旦找到元素就停止工作.它是用C语言编写的,它的Perl等价物就像这个子程序:
sub first (&@) {
my $code = shift;
foreach (@_) {
return $_ if &{$code}();
}
undef;
}
Run Code Online (Sandbox Code Playgroud)
如果速度很少受到关注,那么常见的习惯用法在标量上下文中使用grep(它返回通过其条件的项目数)来遍历整个列表.这确实有利于告诉你它找到了多少匹配.
my $is_there = grep $_ eq $whatever, @array;
Run Code Online (Sandbox Code Playgroud)
如果要实际提取匹配元素,只需在列表上下文中使用grep.
my @matches = grep $_ eq $whatever, @array;
Run Code Online (Sandbox Code Playgroud)
dra*_*tun 15
使用List :: Util中的第一个函数,它是Perl的标准配置....
use List::Util qw/first/;
my @a = qw(foo bar baz);
if ( first { $_ eq 'bar' } @a ) { say "Found bar!" }
Run Code Online (Sandbox Code Playgroud)
NB.first返回它找到的第一个元素,因此不必遍历完整列表(这是grep将要执行的操作).
一种可能的方法是使用List :: MoreUtils'any'函数.
use List::MoreUtils qw/any/;
my @array = qw(foo bar baz);
print "Exist\n" if any {($_ eq "foo")} @array;
Run Code Online (Sandbox Code Playgroud)
更新:根据zoul的评论更正.
有趣的解决方案,尤其是重复搜索:
my %hash;
map { $hash{$_}++ } @a;
print $hash{$val};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
35848 次 |
| 最近记录: |