当前位置:  开发笔记 > 编程语言 > 正文

如何验证Perl中的数组(列表)中是否存在值?

如何解决《如何验证Perl中的数组(列表)中是否存在值?》经验,为你挑选了6个好方法。

我有一个可能的值列表:

@a = qw(foo bar baz);

如何以简明的方式检查值$val是否存在@a

一个明显的实现是遍历列表,但我确信TMTOWTDI.


感谢所有回答的人!我想强调的三个答案是:

    接受的答案 - 最"内置"和向后兼容的方式.

    RET的答案是最干净的,但只适用于Perl 5.10及更高版本.

    draegtun的答案(可能)有点快,但需要使用额外的模块.我不喜欢添加依赖项,如果我可以避免它们,在这种情况下不需要性能差异,但如果你有一个1,000,000元素的列表,你可能想尝试这个答案.

RET.. 38

如果您有perl 5.10,请使用智能匹配运算符 ~~

print "Exist\n" if $var ~~ @array;

这几乎是魔术.



1> RET..:

如果您有perl 5.10,请使用智能匹配运算符 ~~

print "Exist\n" if $var ~~ @array;

这几乎是魔术.



2> Cheekysoft..:

Perl在grep()函数中的优势就是为此而设计的.

@matches = grep( /^MyItem$/, @someArray ); 

或者您可以将任何表达式插入匹配器

@matches = grep( $_ == $val, @a ); 



3> brian d foy..:

这在perlfaq4的答案中得到了回答:"如何判断某个元素是否包含在列表或数组中?" .

要搜索perlfaq,您可以使用自己喜欢的浏览器在perlfaq中搜索所有问题的列表.

从命令行,您可以使用-q开关来perldoc搜索关键字.您可以通过搜索"列表"找到您的答案:

perldoc -q list

(这个答案的部分内容由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"
    }

使用早期版本的Perl,您需要做更多的工作.如果要在任意字符串值上多次进行此查询,最快的方法可能是反转原始数组并维护一个哈希,其键是第一个数组的值:

@blues = qw/azure cerulean teal turquoise lapis-lazuli/;
%is_blue = ();
for (@blues) { $is_blue{$_} = 1 }

现在你可以检查$ 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;

现在你检查$ is_tiny_prime [$ some_number].

如果有问题的值是整数而不是字符串,则可以使用位字符串来节省相当多的空间:

@articles = ( 1..10, 150..2000, 2017 );
undef $read;
for (@articles) { vec($read,$_,1) = 1 }

现在检查一些$ n的vec($ read,$ n,1)是否为真.

这些方法保证了快速的单独测试,但需要重新组织原始列表或数组.如果必须针对同一阵列测试多个值,它们只会得到回报.

如果您只测试一次,标准模块List :: Util会首先导出该功能.它一旦找到元素就停止工作.它是用C语言编写的,它的Perl等价物就像这个子程序:

sub first (&@) {
    my $code = shift;
    foreach (@_) {
        return $_ if &{$code}();
    }
    undef;
}

如果速度很少受到关注,那么常见的习惯用法在标量上下文中使用grep(它返回通过其条件的项目数)来遍历整个列表.这确实有利于告诉你它找到了多少匹配.

my $is_there = grep $_ eq $whatever, @array;

如果要实际提取匹配元素,只需在列表上下文中使用grep.

my @matches = grep $_ eq $whatever, @array;



4> draegtun..:

使用List :: Util中的第一个函数,它是Perl的标准配置....

use List::Util qw/first/;

my @a = qw(foo bar baz);
if ( first { $_ eq 'bar' } @a ) { say "Found bar!" }

NB.first返回它找到的第一个元素,因此不必遍历完整列表(这是grep将要执行的操作).



5> neversaint..:

一种可能的方法是使用List :: MoreUtils'any'函数.

use List::MoreUtils qw/any/;

my @array = qw(foo bar baz);

print "Exist\n" if any {($_ eq "foo")} @array;

更新:根据zoul的评论更正.



6> zoul..:

有趣的解决方案,尤其是重复搜索:

my %hash;
map { $hash{$_}++ } @a;
print $hash{$val};

推荐阅读
mobiledu2402852357
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有