2009-08-07 33 views
6

Étant donné un fichier d'entrée de lignes de texte, je veux que les lignes en double soient identifiées et supprimées. S'il vous plaît montrer un extrait simple de C# qui accomplit cela.Supprimer des lignes en double à partir du fichier texte?

+0

Il existe différentes méthodes, certaines plus faciles à mettre en œuvre que d'autres. L'approche à adopter peut dépendre de la taille du fichier texte et du nombre attendu de lignes correspondantes. Pouvez-vous décrire le problème spécifique que vous essayez de résoudre? Merci :) –

+0

. . . et la performance souhaitée. –

Répondre

18

Cela devrait faire (et copier des fichiers volumineux).

Notez qu'il supprime uniquement dupliquer consécutifs lignes, à savoir

a 
b 
b 
c 
b 
d 

finira comme

a 
b 
c 
b 
d 

Si vous voulez pas de doublons partout, vous aurez besoin de garder un ensemble de lignes que vous avez déjà vues.

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

Notez que cela suppose Encoding.UTF8, et que vous voulez utiliser des fichiers. Il est facile de généraliser comme méthode si:

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

(. Notez que cela ne se ferme pas quoi que ce soit - l'appelant doit faire)

Voici une version qui supprimera tous doublons, plutôt que juste consécutifs:

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

Pour les petits fichiers:

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

Je me demande comment il gère le .Distinct() sur le T []. – user7116

+0

Il semble que Distinct utilise une classe Set interne qui semble être une classe HashSet réduite. Les «lignes» fournies ne sont pas très grandes. mémoire cela devrait très bien fonctionner. – user7116

2

Pour un fichier long (et duplications non consécutifs) je serais copier la ligne de fichiers en ligne la construction d'un hachage // position de table de recherche que je suis allé.

Lorsque chaque ligne est copiée, vérifiez la valeur hachée, s'il y a une double vérification de collision, que la ligne est la même et passe à la suivante. (

ne vaut que pour les fichiers assez grand cependant.

2

est ici une approche de streaming qui devrait supporter moins de frais généraux que la lecture de toutes les chaînes uniques en mémoire.

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

Il nécessite moins de mémoire, mais produit également une sortie incorrecte en cas de collision par hachage. –

0

Je suis nouveau .net & ont écrit quelque chose de plus simple, peut-être pas très efficace.S'il vous plaît remplir gratuitement pour partager vos commentaires

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

Une pensée: il serait utile que vous puissiez commenter votre code pour expliquer ce que vous faites (et pourquoi) - cela aidera les autres à comprendre votre méthodologie et à l'appliquer à leurs situations à l'avenir. –

Questions connexes