我循环遍历一个数组,我想测试是否在另一个数组中找到了一个元素.
在伪代码中,我想要做的是:
foreach $term (@array1) {
if ($term is found in @array2) {
#do something here
}
}
Run Code Online (Sandbox Code Playgroud)
我已经得到了"foreach"和"在这里做点什么"的部分......但是我为"如果在数组中找到术语"测试所尝试的一切都不起作用......
我试过grep:
if grep {/$term/} @array2 { #do something }
# this test always succeeds for values of $term that ARE NOT in @array2
if (grep(/$term/, @array2)) { #do something }
# this test likewise succeeds for values NOT IN the array
Run Code Online (Sandbox Code Playgroud)
我已经尝试了几种不同的"将数组转换为哈希"的方式,许多以前的帖子都指出这些方法非常简单易用......而且没有一个有效.
我是perl的长期低级用户,我只了解perl的基础知识,不明白所有花哨的混淆代码,包含99%我在interwebs上读到的解决方案......我真的,真的,老老实实地欣赏代码中明确的任何答案,并提供代码正在做什么的逐步解释......
...我认真地不要理解$ _以及任何其他种类或类型的隐藏,理解或暗示的价值,变量或功能.如果任何示例或示例的所有变量和函数都以明确的术语命名($ term而不是$ _),我会非常感激...并用注释描述代码正在做什么,所以我,在我所有的精神缺陷的荣耀中,可能希望有一天能够理解它.请.:-)
...
我有一个现有的脚本使用'grep'有点成功:
$rc=grep(/$term/, @array);
if ($rc eq 0) { #something happens here }
Run Code Online (Sandbox Code Playgroud)
但是我将那个完全相同的代码应用到我的新脚本中它只是没有正确成功...即,当它测试$ term的值时,它"成功"(rc = 0),我知道该数组中不存在测试.我只是不明白.
我在'旧'脚本和'新'脚本之间'grep'方法的唯一区别在于我是如何构建数组的......在旧脚本中,我通过从文件中读入来构建数组:
@array=`cat file`;
Run Code Online (Sandbox Code Playgroud)
而在新脚本中我把数组放在脚本本身(因为它很小)...像这样:
@array=("element1","element2","element3","element4");
Run Code Online (Sandbox Code Playgroud)
怎么会导致grep函数的输出不同?它们都是沼泽标准阵列!我不明白!!!! :-(
################################################## ######################我试图匹配/找到/ grep的术语是一个单词元素,例如"word123".
这个练习只是为了从一个充满垃圾的文件中找到一些重要信息的快速脏脚本,所以我跳过所有的细节(使用严格,警告,模块,子程序)选择......这不是'必须优雅,简单.
我正在搜索的术语存储在一个变量中,该变量通过split实例化:
foreach $line(@array1) {
chomp($line); # habit
# every line has multiple elements that I want to capture
($term1,$term2,$term3,$term4)=split(/\t/,$line);
# if a particular one of those terms is found in my other array 'array2'
if (grep(/$term2/, @array2) {
# then I'm storing a different element from the line into a 3rd array which eventually will be outputted
push(@known, $term1) unless $seen{$term1}++;
}
}
Run Code Online (Sandbox Code Playgroud)
看到grep在那里?它不能正常工作......即使它绝对不在array2中,它也是$ term2的所有值的成功... array1是一个几千行的文件.我在这里调用$ term2的元素是一个离散项,可以是多行,但在任何给定行中都不会重复(或者是较大字符串的一部分).Array2是我需要"过滤"输出的几十个元素.
...
我刚刚尝试了以下建议之一:
if (grep $_ eq $term2, @array2)
Run Code Online (Sandbox Code Playgroud)
这个grep对于$ term2的所有值都失败了...我得到grep的全部或全部响应...所以我想我需要停止使用grep.尝试其中一种哈希解决方案......但我真的可以使用更多的解释和澄清.
这是在perlfaq.一个快速的方法是
my %seen;
$seen{$_}++ for @array1;
for my $item (@array2) {
if ($seen{$item}) {
# item is in array2, do something
}
}
Run Code Online (Sandbox Code Playgroud)
如果字母大小写不重要,您可以设置密钥$seen{ lc($_) }
并检查if ($seen{ lc($item) })
.
ETA:
随着问题的改变:如果任务是匹配@array2
整行中的单个单词@array1
,则任务更复杂.由于标点符号和其他类似的东西,尝试拆分行并与哈希键匹配可能是不安全的.因此,正则表达式解决方案可能是最安全的.
除非@array2
是非常大的,你可能会做这样的事情:
my $rx = join "|", @array2;
for my $line (@array1) {
if ($line =~ /\b$rx\b/) { # use word boundary to avoid partial matches
# do something
}
}
Run Code Online (Sandbox Code Playgroud)
如果@array2
包含元字符,例如*?+|
,您必须确保它们被转义,在这种情况下,您可以执行以下操作:
my $rx = join "|", map quotemeta, @array2;
# etc
Run Code Online (Sandbox Code Playgroud)
如果您使用的是5.10或更高版本,则可以使用(臭名昭着的)"智能匹配"运算符:
#!/usr/bin/perl
use strict;
use warnings;
my @array1 = qw/a b c d e f g h/;
my @array2 = qw/a c e g z/;
print "a in \@array1\n" if 'a' ~~ @array1;
print "z in \@array1\n" if 'z' ~~ @array1;
print "z in \@array2\n" if 'z' ~~ @array2;
Run Code Online (Sandbox Code Playgroud)
示例非常简单,但如果您需要,也可以使用RE.我应该补充一点,不是每个人都喜欢~~因为有一些歧义,嗯,"没有文档的功能".虽然应该可以.
这应该工作.
#!/usr/bin/perl
use strict;
use warnings;
my @array1 = qw/a b c d e f g h/;
my @array2 = qw/a c e g z/;
for my $term (@array1) {
if (grep $_ eq $term, @array2) {
print "$term found.\n";
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
a found.
c found.
e found.
g found.
Run Code Online (Sandbox Code Playgroud)