【问题标题】:How might I remove duplicate lines from a file?如何从文件中删除重复的行?
【发布时间】:2010-11-15 22:59:29
【问题描述】:

我有一个包含一列的文件。如何删除文件中的重复行?

【问题讨论】:

    标签: python text file-io


    【解决方案1】:

    如果您使用的是 *nix,请尝试运行以下命令:

    sort <file name> | uniq
    

    【讨论】:

      【解决方案2】:

      在 Unix/Linux 上,使用 uniq 命令,根据 David Locke 的回答,或 sort,根据 William Pursell 的评论。

      如果您需要 Python 脚本:

      lines_seen = set() # holds lines already seen
      outfile = open(outfilename, "w")
      for line in open(infilename, "r"):
          if line not in lines_seen: # not a duplicate
              outfile.write(line)
              lines_seen.add(line)
      outfile.close()
      

      更新:sort/uniq 组合将删除重复项,但返回一个文件,其中行已排序,这可能是也可能不是您想要的。上面的 Python 脚本不会重新排序行,而只是删除重复项。当然,要让上面的脚本也进行排序,只需省略outfile.write(line),而是在循环之后立即执行outfile.writelines(sorted(lines_seen))

      【讨论】:

      • 您需要在运行 uniq 之前运行 sort,因为 uniq 只会删除与前一行相同的行。
      • 是的 - 我提到了你的回答,但没有重申它是 sort 后跟 uniq。
      • 这个解决方案+1。进一步的增强可能是存储行的 md5 总和,并比较当前行的 md5 总和。这应该会显着减少内存需求。 (见docs.python.org/library/md5.html
      • +1 我本可以自己写这段代码,但是当你可以谷歌的时候为什么还要写:)
      • 这个答案给Traceback (most recent call last): File "sort and unique.py", line 5, in &lt;module&gt; outfile.write(line) MemoryError 如何解决它
      【解决方案3】:
      uniqlines = set(open('/tmp/foo').readlines())
      

      这将为您提供唯一行的列表。

      将其写回某个文件就像这样简单:

      bar = open('/tmp/bar', 'w').writelines(set(uniqlines))
      
      bar.close()
      

      【讨论】:

      • 是的,但是这些行将根据它们的散列方式以某种随机顺序排列。
      • 这段代码的问题是你写完之后,最后一行没有'\n'。然后输出结果将有 1 行合并 2 行。
      • 您的解决方案适用于较小的文件。其中文件大小高达 300mb 或 400mb。不止于此。
      【解决方案4】:

      在列表中获取所有行并制作一组行,您就完成了。 例如,

      >>> x = ["line1","line2","line3","line2","line1"]
      >>> list(set(x))
      ['line3', 'line2', 'line1']
      >>>
      

      如果您需要保留行的顺序 - 因为 set 是无序集合 - 试试这个:

      y = []
      for l in x:
          if l not in y:
              y.append(l)
      

      并将内容写回文件。

      【讨论】:

      • 是的,但是这些行将根据它们的散列方式以某种随机顺序排列。
      【解决方案5】:

      这是我的解决方案

      if __name__ == '__main__':
      f = open('temp.txt','w+')
      flag = False
      with open('file.txt') as fp:
          for line in fp:
              for temp in f:
                  if temp == line:
                      flag = True
                      print('Found Match')
                      break
              if flag == False:
                  f.write(line)
              elif flag == True:
                  flag = False
              f.seek(0)
          f.close()
      

      【讨论】:

        【解决方案6】:

        Python One 衬垫:

        python -c "import sys; lines = sys.stdin.readlines(); print ''.join(sorted(set(lines)))" < InputFile > OutputFile
        

        【讨论】:

          【解决方案7】:

          你可以这样做:

          import os
          os.system("awk '!x[$0]++' /path/to/file > /path/to/rem-dups")
          

          这里你正在使用 bash 进入 python :)

          你还有其他办法:

          with open('/tmp/result.txt') as result:
                  uniqlines = set(result.readlines())
                  with open('/tmp/rmdup.txt', 'w') as rmdup:
                      rmdup.writelines(set(uniqlines))
          

          【讨论】:

            【解决方案8】:

            这是对这里已经说过的内容的重述 - 这是我使用的内容。

            import optparse
            
            def removeDups(inputfile, outputfile):
                    lines=open(inputfile, 'r').readlines()
                    lines_set = set(lines)
                    out=open(outputfile, 'w')
                    for line in lines_set:
                            out.write(line)
            
            def main():
                    parser = optparse.OptionParser('usage %prog ' +\
                                    '-i <inputfile> -o <outputfile>')
                    parser.add_option('-i', dest='inputfile', type='string',
                                    help='specify your input file')
                    parser.add_option('-o', dest='outputfile', type='string',
                                    help='specify your output file')
                    (options, args) = parser.parse_args()
                    inputfile = options.inputfile
                    outputfile = options.outputfile
                    if (inputfile == None) or (outputfile == None):
                            print parser.usage
                            exit(1)
                    else:
                            removeDups(inputfile, outputfile)
            
            if __name__ == '__main__':
                    main()
            

            【讨论】:

              【解决方案9】:

              添加到@David Locke 的答案,您可以使用 *nix 系统运行

              sort -u messy_file.txt > clean_file.txt
              

              这将创建clean_file.txt 按字母顺序删除重复项。

              【讨论】:

              • 这将删除重复项,但会修改(排序)行的顺序。不完全是问什么。
              【解决方案10】:

              如果有人正在寻找使用散列的解决方案并且更华丽一点,这就是我目前使用的:

              def remove_duplicate_lines(input_path, output_path):
              
                  if os.path.isfile(output_path):
                      raise OSError('File at {} (output file location) exists.'.format(output_path))
              
                  with open(input_path, 'r') as input_file, open(output_path, 'w') as output_file:
                      seen_lines = set()
              
                      def add_line(line):
                          seen_lines.add(line)
                          return line
              
                      output_file.writelines((add_line(line) for line in input_file
                                              if line not in seen_lines))
              

              【讨论】:

              • 当您可以只添加行本身时,将行的 HASH 添加到集合中的意义何在?
              【解决方案11】:

              查看我创建的用于从文本文件中删除重复电子邮件的脚本。希望这会有所帮助!

              # function to remove duplicate emails
              def remove_duplicate():
                  # opens emails.txt in r mode as one long string and assigns to var
                  emails = open('emails.txt', 'r').read()
                  # .split() removes excess whitespaces from str, return str as list
                  emails = emails.split()
                  # empty list to store non-duplicate e-mails
                  clean_list = []
                  # for loop to append non-duplicate emails to clean list
                  for email in emails:
                      if email not in clean_list:
                          clean_list.append(email)
                  return clean_list
                  # close emails.txt file
                  emails.close()
              # assigns no_duplicate_emails.txt to variable below
              no_duplicate_emails = open('no_duplicate_emails.txt', 'w')
              
              # function to convert clean_list 'list' elements in to strings
              for email in remove_duplicate():
                  # .strip() method to remove commas
                  email = email.strip(',')
                  no_duplicate_emails.write(f"E-mail: {email}\n")
              # close no_duplicate_emails.txt file
              no_duplicate_emails.close()
              

              【讨论】:

                【解决方案12】:

                在同一个文件中编辑它

                lines_seen = set() # holds lines already seen
                
                with open("file.txt", "r+") as f:
                    d = f.readlines()
                    f.seek(0)
                    for i in d:
                        if i not in lines_seen:
                            f.write(i)
                            lines_seen.add(i)
                    f.truncate()
                

                【讨论】:

                  【解决方案13】:

                  可读性强

                  with open('sample.txt') as fl:
                      content = fl.read().split('\n')
                  
                  content = set([line for line in content if line != ''])
                  
                  content = '\n'.join(content)
                  
                  with open('sample.txt', 'w') as fl:
                      fl.writelines(content)
                  

                  【讨论】:

                  • 最好使用打开上下文管理器打开文件,以便安全关闭。如果文件很大,也可能无法一次性读取全部内容。
                  【解决方案14】:
                  cat <filename> | grep '^[a-zA-Z]+$' | sort -u > outfile.txt
                  

                  从文件中过滤和删除重复值。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2023-03-10
                    • 2011-11-08
                    • 1970-01-01
                    • 2014-06-03
                    • 2012-04-05
                    • 2018-01-31
                    相关资源
                    最近更新 更多