2009-08-07 57 views
6

Dado un archivo de entrada de líneas de texto, quiero que se identifiquen y eliminen las líneas duplicadas. Muestre un fragmento simple de C# que logre esto.Eliminar líneas duplicadas del archivo de texto?

+0

Existen varios métodos, algunos más fáciles de implementar que otros. El enfoque que se debe tomar depende del tamaño del archivo de texto y del número esperado de líneas coincidentes. ¿Puedes describir el problema específico que intentas resolver? Gracias :) –

+0

. . . y el rendimiento deseado. –

Respuesta

18

Esto debería hacer (y copiará con archivos de gran tamaño).

Tenga en cuenta que sólo la quita duplicar líneas consecutivas, es decir

a 
b 
b 
c 
b 
d 

va a terminar como

a 
b 
c 
b 
d 

Si desea duplicados en cualquier lugar, usted necesita para mantener un conjunto de líneas que ya has visto

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; 
       } 
      } 
     } 
    } 
} 

Tenga en cuenta que esto supone Encoding.UTF8, y que desea utilizar los archivos. Es fácil generalizar como un método sin embargo:

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; 
     } 
    } 
} 

(. Tenga en cuenta que que no cierra nada - la persona que llama debe hacer eso)

Aquí hay una versión que eliminará todos duplicados, en lugar de que se acaban consecutivos:

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

los archivos pequeños:

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

Me pregunto cómo maneja el .Distinct() en el T []. – user7116

+0

Parece que Distinct usa una clase Set interna que parece ser una clase HashSet reducida. Siempre que 'líneas' no sea terriblemente grande w.r.t. memoria esto debería funcionar muy bien. – user7116

2

para un archivo largo (y duplicaciones no consecutivos) que habían copiar archivos de la línea por línea de la construcción de una tabla de búsqueda de hash // posición como fui.

A medida que se copia cada línea, compruebe el valor hash, si hay una colisión, compruebe que la línea sea la misma y pase a la siguiente. (

sólo vale la pena para los archivos bastante grandes sin embargo.

2

Aquí es un enfoque streaming que debe incurrir en menos gastos generales que la lectura de todas las cadenas únicas en la memoria.

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

Requiere menos memoria, pero también produce salida incorrecta si hay una colisión hash. –

0

Soy nuevo a .NET & tienen escrito algo más simple, puede no ser muy eficiente.Por favor, rellene gratis para compartir sus pensamientos.

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

Un pensamiento: sería útil si pudieras comentar tu código para explicar lo que estás haciendo (y por qué), eso ayudará a otros a entender tu metodología y aplicarla a sus situaciones en el futuro. –

Cuestiones relacionadas