2012-02-06 97 views
0

我有两个数组@input0@input1。我想要一个循环遍历@input1中的每个值,如果值存在于@input0中,则该值将保存在新数组@input中。使用Perl查找数组中的值

所有数组仅包含数字。最多有每个数组元素10个号码是(见下文):

@input0 = {10061 10552 10553 10554 10555 10556 10557 10558 10559 10560, 10561 10562 10563 10564 10565 10566 10567 10573 10574 10575, ...} 

@input1 = {20004 20182 ...} 
+1

'@ input0 = {10061 10552 ....,10561 ...}'不是有效的perl语法,并且会给出错误,例如'在操作符期望的地方找到的数字'。你需要引用字符串“10061 10552 ...”。此外,大括号'{}'创建一个哈希引用。分配给数组时,你需要常规parens'()'。 – TLP 2012-02-06 14:53:21

回答

2

短,甜又慢:

my @input = grep $_ ~~ @input0, @input1; 

繁琐,更快的for循环:

my %input0 = map {$_, 1} @input0; 
my @input; 

for (@input1) { 
    push @input, $_ if $input0{$_}; 
} 
+0

智能匹配仅适用于Perl 5.10及以上版本,并且不能在早期使用。 – DVK 2012-02-06 11:41:50

+1

这对于大型阵列来说也是比较慢的,因为它会进行O(N * M)扫描,而不是I(N + M)作为map + grep – DVK 2012-02-06 11:42:51

+0

确实如此,但是你却把我击败了惯用的解决方案。如果有的话,这个解决方案使乍一看更易于说明它创建了两个数组的交集。 – flesk 2012-02-06 11:51:12

7

最简洁和惯用的方式来实现这在Perl不是经由使用“for”循环,但是mapgrep

my %seen0 = map { ($_ => 1) } @input0; 
my @input = grep { $seen0{$_} } @input1; 

如果你特别想要一个for循环,请解释为什么地图/ grep的方法是行不通的(除非它是在这种情况下,这个问题应被标记为一个作业)

+0

+1。习惯解决方案是惯用的。 – flesk 2012-02-06 11:52:47

+0

这似乎并不奏效。我猜是因为我每个数组元素有多个数字(最多10个,用空格分隔)。对不起,应该提到这一点。那么我最好先将数组分成每个元素的单个数字?谢谢 – 2012-02-06 12:43:42

+0

@charleshendry - 如果你有一个空格分隔的字符串,它不会被称为“数组”。您需要提供更准确的说明和示例 – DVK 2012-02-06 12:50:06

1

你也可以使用一个hashslice +的grep:

my %tmp ; 
@tmp{@input0} = undef ; # Fill all elements of @input0 in hash with value undef 
my @input = grep { exists $tmp{$_} } @input1 ; # grep for existing hash keys 
0

DGW的回答几乎是有,但包含一对夫妇的事情,AREN最佳实践。我相信这是好:

my %input0_map; 
@input0_map{ @input0 } =(); 
my @input = grep { exists $input0_map{$_} } @input1; 

你不应该命名变量“TMP”,除非它是在一个非常小的范围内。由于此代码片段未包含在括号内,因此我们不知道该作用域有多大。

您不应该使用单个'undef'分配散列片,因为​​这意味着第一个元素被分配了undef的文字,其他元素被分配了隐含的undefs。它会工作,但它是不好的风格。可以将它们全部赋值为一个值,或者让它们全部隐式赋值(如果我们从空列表中分配)。