我有一个看起来像这样的CSV文件:
foo,bar,glib
"a","1","A"
"b","1","B"
"a","2","C"
"b","1","D"
我正在遍历该CSV文件,并想删除foo
和bar
相同的所有重复行,即,我生成的文件应如下所示:
foo,bar,glib
"a","1","A"
"b","1","B"
"a","2","C"
这就是我的做法:
require "csv"
File.open("input.csv") do |infile|
reader = CSV.new(infile, header=true)
File.open("output.csv", "w") do |outfile|
printed_tuples = Array(Tuple(String, String)).new
CSV.build(outfile) do |writer|
while reader.next
next if printed_tuples.includes?({reader.row["foo"], reader.row["bar"]})
printed_tuples << {reader.row["foo"], reader.row["bar"]}
writer.row reader.row.to_a
end
end
end
end
真正的CSV文件要大得多(386280行和17列),而且速度太慢以至于几乎无法使用。
具有讽刺意味的是,我一直在重写python脚本,因为我曾希望能获得更好的性能,但现在python版本要快得多。
有人对如何加快速度有任何指示吗?
答案 0 :(得分:5)
关键操作是搜索现有值。 Array#includes?
在这种情况下效率很低:它需要遍历所有先前的行(对于重复的行,不是全部,而是通常其中的一半)。为每一行执行该操作,即O(N²)
。
您需要一个可以更快搜索的不同数据结构。 Crystal具有Set
类型,该类型由哈希表支持。
也许有更好的数据结构和算法可以解决此问题,但是Set
在Crystal的标准库中可用,应该已经做了很多改进。