2010-06-21 165 views
2

我写了一个perl脚本,它打开两个包含列表的文件。我想查找第一个列表中不在第二个列表中的项目。该脚本使用两个foreach循环。外循环遍历第一个列表的每一行,提取必要的项目信息。内循环遍历第二个列表,提取项目信息,然后将该信息与第一个列表中的项目进行比较。在perl中嵌套的foreach循环只循环一次

所以,这个想法是,对于第一个列表中的每个项目,脚本将遍历第二个列表中的所有项目,寻找匹配项。麻烦的是内部的foreach循环只循环一次。在嵌套的while循环中循环遍历MySQL表时,我在PHP中遇到了同样的问题。解决方案是使用mysql_data_seek为外部循环的每次迭代重置mysql数据的索引。我如何在perl中使用文件句柄来做到这一点?

+8

你能发表一些解释你现在在做什么的代码吗? – azatoth 2010-06-21 16:44:30

+2

如果你显示你的代码,人们将能够指出什么是错的。没有它,人们只能推测,你只是在浪费他们(和你的)时间。 – 2010-06-21 16:44:45

+0

如果没有代码,我无法回答,但有可能是在外循环的内循环中重新使用某些内容,如文件句柄或循环计数器。 – 2010-06-21 16:45:34

回答

8

如果你的内循环是一个文件句柄迭代器,那么每当你达到它时你都需要重置它(例如关闭并重新打开文件)。

foreach my $outer (@outer) { 
    open INNER, '<', $inner_file; # <--- need to add this 
    while (my $inner = <INNER>) { 
     ... 
    } 
    close INNER;     # <--- optional with global scope filehandle 
} 

或者,如果可以备用存储器中,则可以将文件句柄输出复制到阵列中的环的外侧,然后迭代这个数组。

open INNER, '<', $inner_file; 
my @INNER = <INNER>; 
close INNER; 

foreach my $outer (@outer) { 
    foreach my $inner (@INNER) { 
     ... 
    } 
} 
+0

谢谢,这是一个很好的答案,正是我所需要的。 – smfoote 2010-06-21 16:52:23

+2

@smfoote,不要只说“谢谢”,将它投票并检查旁边的复选标记。并且在将来,请在您的问题中发布一些代码。 – 2010-06-21 16:55:17

+1

我没有足够的声望投票,我确实检查了复选标记。我知道有代码通常是有用的,但我认为这个问题不需要代码,并且证据是,mobrule能够在不看代码的情况下轻松回答问题。 通常,当我添加我的代码时,答案和评论会分散注意力,我开始试着弄清楚,而且人们开始讲授我的代码质量。我不是那样的粉丝。 – smfoote 2010-06-21 17:20:05

3

应当注意的是,当你描述它的代码听起来很低效,为O(n 米)。您可以通过将一个文件的相关内容放入哈希中,然后迭代另一个文件一次来获得O(n + m)效率。

+0

如果我把第一个文件的相关内容放在一个散列中,然后迭代第二个文件,我想我仍然需要在第二个文件的每次迭代中运行散列。代码绝对可以更高效,但是这两个文件都不是很大,所以差别不会超过几秒钟。无论如何,我应该修复它,所以我不会有坏习惯。 – smfoote 2010-06-25 21:47:57

+1

@smfoote:如果您可以设计散列,以便您可以通过键进行比较,则此比较将变为_O(1)_相对于散列大小而不是_O(n)_。散列的“诀窍”是你不必诉诸于二进制搜索(_O(log n)_)。 – Svante 2010-06-26 12:19:42