繁体   English   中英

Ruby中2个文件之间的匹配模式列表

[英]Matching pattern list between 2 files in Ruby

我正在尝试从Input.txt打印包含ValuesToSearch.txt中的字符串的 我下面显示的当前脚本可以打印正确的输出,但是当我尝试使用Input.txt包含950万行而ValuesToSearch.txt包含300行的实际数据时,处理速度非常慢。

如何修改脚本以获得更快的输出? 谢谢

Input.txt

ID       HM    PRAO  LN  AC
1401144  851    2    45   32
1401145  6D2    4    45   32
1401146  B33    1    45   32
1401147  EEC    9    45   32
1401148  730    1    45   32
1401149  C08    3    45   32
1401150  B91    4    45   32
1401151  978    1    45   32
1401152  6A9    0    45   32

ValuesToSearch.txt

1401176
1401148
1401149
1401151

我的剧本:

ruby -e '
a=File.foreach("Input.txt").map {|l| l.split(" ")}
b=File.foreach("ValuesToSearch.txt").map {|l| l.split(" ")}.flatten

b.map{ |z| 
    a.map{ |i| puts i.join(" ") if i.include?(z) } 
}'

1401148 730 1 45 32
1401149 C08 3 45 32
1401151 978 1 45 32

那这个呢?

dict = File.read('/tmp/ValuesToSearch.txt').split.inject({}) do |acc, word|
  acc[word] = true
  acc
end

File.foreach('/tmp/Input.txt') do |line|
  puts line if line.split.any? { |word| dict[word] }
end

在这种方法中,我使用哈希来存储“要搜索的值”。
因此,我们可以搜索O(1)(而不是O(N))。

而且您不需要在Input.txt的单词中重复两次。
您可以在单次迭代中打印所需的行。

并按照@tadman的建议,将此脚本放入文件中,然后使用ruby myscript.rb执行它。

首先让我们创建两个文件。

VTS_FName = "ValuesToSearch.txt"
vts_data = <<-_
1401176
1401148
1401149
1401151
_
File.write(VTS_FName, vts_data)
  #=> 32

IT_FName = "Input.txt"
it_data = <<-_
ID       HM    PRAO  LN  AC
1401144  851    2    45   32
1401145  6D2    4    45   32
1401146  B33    1    45   32
1401147  EEC    9    45   32
1401148  730    1    45   32
1401149  C08    3    45   32
1401150  B91    4    45   32
1401151  978    1    45   32
1401152  6A9    0    45   32
_
File.write(IT_FName, it_data)
  #=> 289

效率的关键是使VTS_FName的内容VTS_FName一个集合,而不是一个数组。

require 'set'

vts_set = File.readlines(VTS_FName).map(&:chomp).to_set
File.foreach(IT_FName) { |line| puts line if vts_set.include?(line[/\d+/]) }
1401148  730    1    45   32
1401149  C08    3    45   32
1401151  978    1    45   32

要保存匹配的行,而不是打印它们,请使用以下命令(在创建vts_set )。

File.foreach(IT_FName).with_object([]) { |line, arr|
  arr << line.chomp if vts_set.include?(line[/\d+/]) }
  #=> ["1401148  730    1    45   32",
  #    "1401149  C08    3    45   32",
  #    "1401151  978    1    45   32"]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM