2009-08-07 45 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