2

我有一个包含一些重复条目的文件。看起来像

Los Angeles, 6
Los Angeles, 6 
New York, 31
New York, 31
New YOrk, 31
.
.
.

现在我想摆脱重复的数据。我尝试做的是使用each_line,查看该行是否等于下一行,如果它们相同,则跳过并写入一个新文件。问题是我应该如何获得该文件的下一行?或任何其他建议来做到这一点?

4

5 回答 5

5

无需与下一行进行比较,因为您可以轻松查看当前行是否与上一行匹配:

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
}
于 2012-09-21T21:57:55.290 回答
3

如果重复项总是连续的,则 willglynn 的解决方案有效。否则,我认为最好的方法是将它们放入哈希中。

unique_list = {}

File.foreach(filename) do |line|
  unique_list[line] = 1
end

unique_list.each do |line|
  new_file.print line
end
于 2012-09-21T23:45:55.410 回答
2

如果重复的行是连续的,你可以写:

lines = open("file.txt").each_line.chunk(&:downcase).lazy.map { |s, ss| ss.first }

替换downcase您决定哪些字符串等价的函数。

于 2012-09-21T22:04:35.783 回答
1

如果您可以从 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
于 2014-03-21T15:31:28.977 回答
0

以@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
于 2016-08-28T01:50:04.557 回答