2009-08-07 71 views
6

给定一个文本行的输入文件,我想重复的行被识别和删除。请展示一个简单的C#代码片段来完成此操作。删除文本文件中的重复行?

+0

有很多方法,有些更容易实现相对于其它的。要采取的方法可能取决于文本文件的大小和匹配行的预期数量。你能描述你想解决的具体问题吗?谢谢:) – 2009-08-07 15:47:21

+0

。 。 。和期望的表现。 – 2009-08-07 15:48:29

回答

18

这应该做(和将复制大文件)。

注意,它只是删除了重复连续线,即

a 
b 
b 
c 
b 
d 

最终将成为

a 
b 
c 
b 
d 

如果你想在任何地方没有重复,你需要保留一组你已经看到的线条。

using System; 
using System.IO; 

class DeDuper 
{ 
    static void Main(string[] args) 
    { 
     if (args.Length != 2) 
     { 
      Console.WriteLine("Usage: DeDuper <input file> <output file>"); 
      return; 
     } 
     using (TextReader reader = File.OpenText(args[0])) 
     using (TextWriter writer = File.CreateText(args[1])) 
     { 
      string currentLine; 
      string lastLine = null; 

      while ((currentLine = reader.ReadLine()) != null) 
      { 
       if (currentLine != lastLine) 
       { 
        writer.WriteLine(currentLine); 
        lastLine = currentLine; 
       } 
      } 
     } 
    } 
} 

请注意,这里假定Encoding.UTF8,并且您要使用文件。这很容易概括,就像一个方法:

static void CopyLinesRemovingConsecutiveDupes 
    (TextReader reader, TextWriter writer) 
{ 
    string currentLine; 
    string lastLine = null; 

    while ((currentLine = reader.ReadLine()) != null) 
    { 
     if (currentLine != lastLine) 
     { 
      writer.WriteLine(currentLine); 
      lastLine = currentLine; 
     } 
    } 
} 

(请注意,不会关闭任何 - 调用方应该做的)

这里有一个版本,将删除所有重复,而不是只是连续的:

static void CopyLinesRemovingAllDupes(TextReader reader, TextWriter writer) 
{ 
    string currentLine; 
    HashSet<string> previousLines = new HashSet<string>(); 

    while ((currentLine = reader.ReadLine()) != null) 
    { 
     // Add returns true if it was actually added, 
     // false if it was already there 
     if (previousLines.Add(currentLine)) 
     { 
      writer.WriteLine(currentLine); 
     } 
    } 
} 
28

对于小文件:

string[] lines = File.ReadAllLines("filename.txt"); 
File.WriteAllLines("filename.txt", lines.Distinct().ToArray()); 
+0

我不知道它如何处理T []上的.Distinct()。 – user7116 2009-08-10 15:19:11

+0

它看起来像Distinct使用一个内部Set类似乎是一个parred down HashSet类。只要'线路'不是非常大的w.r.t.记忆这应该表现得非常好。 – user7116 2009-08-10 15:23:52

2

对于长文件(和非连续的重复),我会用线建设哈希//位置查找表我去的文件拷贝一行。

复制每一行检查散列值,如果存在冲突,请检查该行是否相同并移至下一行。 (

只有值得的,虽然相当大的文件。

2

这里有一个流媒体的方式应该比读取所有唯一字符串到内存中招致更少的开销。

var sr = new StreamReader(File.OpenRead(@"C:\Temp\in.txt")); 
    var sw = new StreamWriter(File.OpenWrite(@"C:\Temp\out.txt")); 
    var lines = new HashSet<int>(); 
    while (!sr.EndOfStream) 
    { 
     string line = sr.ReadLine(); 
     int hc = line.GetHashCode(); 
     if(lines.Contains(hc)) 
      continue; 

     lines.Add(hc); 
     sw.WriteLine(line); 
    } 
    sw.Flush(); 
    sw.Close(); 
    sr.Close(); 
+1

它需要较少的内存,但如果发生散列冲突,它也会产生不正确的输出。 – 2009-08-07 20:18:54

0

我是新来的.NET &有写一些更简单的东西,可能效率不高。请免费分享您的想法。

class Program 
{ 
    static void Main(string[] args) 
    { 
     string[] emp_names = File.ReadAllLines("D:\\Employee Names.txt"); 
     List<string> newemp1 = new List<string>(); 

     for (int i = 0; i < emp_names.Length; i++) 
     { 
      newemp1.Add(emp_names[i]); //passing data to newemp1 from emp_names 
     } 

     for (int i = 0; i < emp_names.Length; i++) 
     { 
      List<string> temp = new List<string>(); 
      int duplicate_count = 0; 

      for (int j = newemp1.Count - 1; j >= 0; j--) 
      { 
       if (emp_names[i] != newemp1[j]) //checking for duplicate records 
        temp.Add(newemp1[j]); 
       else 
       { 
        duplicate_count++; 
        if (duplicate_count == 1) 
         temp.Add(emp_names[i]); 
       } 
      } 
      newemp1 = temp; 
     } 
     string[] newemp = newemp1.ToArray(); //assigning into a string array 
     Array.Sort(newemp); 
     File.WriteAllLines("D:\\Employee Names.txt", newemp); //now writing the data to a text file 
     Console.ReadLine(); 
    } 
} 
+0

有一个想法:如果你可以评论你的代码来解释你在做什么(以及为什么),这会很有用 - 这将有助于他人理解你的方法并将其应用到他们未来的情况。 – 2016-04-14 19:59:02