我有一个包含一些重复条目的文件。看起来像
Los Angeles, 6
Los Angeles, 6
New York, 31
New York, 31
New YOrk, 31
.
.
.
现在我想摆脱重复的数据。我尝试做的是使用each_line,查看该行是否等于下一行,如果它们相同,则跳过并写入一个新文件。问题是我应该如何获得该文件的下一行?或任何其他建议来做到这一点?
无需与下一行进行比较,因为您可以轻松查看当前行是否与上一行匹配:
file = File.open("filename", "r")
previous_line = nil
file.each_line { |line|
if line == previous_line
# duplicate line; ignore
else
# different; do whatever you want
end
# remember this line so we can compare against it
previous_line = line
}
如果重复项总是连续的,则 willglynn 的解决方案有效。否则,我认为最好的方法是将它们放入哈希中。
unique_list = {}
File.foreach(filename) do |line|
unique_list[line] = 1
end
unique_list.each do |line|
new_file.print line
end
如果重复的行是连续的,你可以写:
lines = open("file.txt").each_line.chunk(&:downcase).lazy.map { |s, ss| ss.first }
替换downcase
您决定哪些字符串等价的函数。
如果您可以从 shell 而不是使用 Ruby 来执行此操作,并且您在 *nix 中工作,那么它会变得更容易。有一个名为uniq的 *nix 工具就是为此而生的。
给定您的示例输入,在文件input.txt中:
Los Angeles, 6
Los Angeles, 6
New York, 31
New York, 31
New YOrk, 31
然后此命令将删除相邻的重复项并将结果打印到标准输出:
$ uniq input.txt
Los Angeles, 6
New York, 31
New YOrk, 31
您会注意到“New York”的第三个实例中的拼写错误导致它不能被识别为重复。
要将结果发送到另一个文件:
$ uniq input.txt >output.txt
$ cat output.txt
Los Angeles, 6
New York, 31
New YOrk, 31
要修改原始文件,您不能将 uniq 的输出重定向到它——您将破坏 uniq 正在读取的输入。相反,使用临时文件:
$ uniq input.txt >input.txt.tmp && cp input.txt.tmp input.txt
$ cat input.txt
Los Angeles, 6
New York, 31
New YOrk, 31
以@Anthony 的回答为基础。我的想法是:
unique_list = {}
new_file=File.open('file2', "w")
File.foreach('filename') do |line|
unique_list[line] = 1
end
unique_list.each do |key,value|
new_file.puts key
end
每一行都成为值为 1 的哈希的键。键是唯一的,因此重复项只会覆盖最后一个。
确保输入字符串末尾没有多余空格后的输出是..
Los Angeles, 6
New York, 31
New YOrk, 31