2010-04-28 5 views
4

Ce que j'ai est deux fichiers, sourcecolumns.txt et destcolumns.txt. Ce que je dois faire est de comparer la source à dest et si la dest ne contient pas la valeur source, écrivez-la dans un nouveau fichier. Le code ci-dessous fonctionne sauf que j'ai des questions sensibles cas comme celui-ci:C# correspondant à deux fichiers texte, sensible à la casse

source: CPI
dest: Cpi

Ces ne correspondent pas à cause de lettres Captial, donc j'obtenir des sorties incorrectes. Toute aide est toujours la bienvenue!

string[] sourcelinestotal = 
    File.ReadAllLines("C:\\testdirectory\\" + "sourcecolumns.txt"); 
string[] destlinestotal = 
    File.ReadAllLines("C:\\testdirectory\\" + "destcolumns.txt"); 

foreach (string sline in sourcelinestotal) 
{ 
    if (destlinestotal.Contains(sline)) 
    { 
    } 
    else 
    { 
     File.AppendAllText("C:\\testdirectory\\" + "missingcolumns.txt", sline); 
    } 
} 

Répondre

5

Vous pouvez le faire en utilisant une méthode d'extension pour IEnumerable<string> comme:

public static class EnumerableExtensions 
{ 
    public static bool Contains(this IEnumerable<string> source, string value, StringComparison comparison) 
    { 
     if (source == null) 
     { 
      return false; // nothing is a member of the empty set 
     } 
     return source.Any(s => string.Equals(s, value, comparison)); 
    } 
} 

puis changer

if (destlinestotal.Contains(sline)) 

à

if (destlinestotal.Contains(sline, StringComparison.OrdinalIgnoreCase)) 

Cependant, si les jeux sont grandes et/ou vous allez faites-le très souvent, la façon dont vous y allez est très inefficace. Essentiellement, vous effectuez une opération O (n) - pour chaque ligne de la source, vous la comparez à potentiellement toutes les lignes de la destination. Il vaudrait mieux créer un HashSet à partir des colonnes de destination avec un comparateur insensi- ble, puis parcourir les colonnes source en vérifiant si chacune existe dans le HashSet des colonnes de destination. Ce serait un algorithme O (n). Notez que Contient sur le HashSet utilisera le comparateur que vous fournissez dans le constructeur.

string[] sourcelinestotal = 
    File.ReadAllLines("C:\\testdirectory\\" + "sourcecolumns.txt"); 
HashSet<string> destlinestotal = 
       new HashSet<string>(
        File.ReadAllLines("C:\\testdirectory\\" + "destcolumns.txt"), 
        StringComparer.OrdinalIgnoreCase 
       ); 

foreach (string sline in sourcelinestotal) 
{ 
    if (!destlinestotal.Contains(sline)) 
    { 
     File.AppendAllText("C:\\testdirectory\\" + "missingcolumns.txt", sline); 
    } 
} 

Avec le recul, je préfère cette solution, tout simplement écrire votre propre insensible cas contient pour IEnumerable<string>, sauf si vous avez besoin de la méthode pour autre chose. Il y a en fait moins de code (de votre choix) à maintenir en utilisant l'implémentation de HashSet.

+0

@aba - dans le cas général, la collection peut contenir la chaîne vide, mais peut-être pas dans ce cas. – tvanfosson

+0

Je ne peux pas obtenir ceci à compiler En utilisant le type générique 'System.Collections.Generic.HashSet 'requiert les arguments de type 1' \t C –

+0

J'ai omis le spécificateur de type sur le constructeur HashSet. J'ai réparé ça. – tvanfosson

0

Si vous n'avez pas besoin sensibilité à la casse, convertir vos lignes en majuscules à l'aide string.ToUpper avant la comparaison.

+5

Non! Cela ne passe pas le test de la Turquie *. http://www.codinghorror.com/blog/2008/03/whats-wrong-with-turkey.html – dtb

+0

Très inefficace - il est préférable d'utiliser les indicateurs de comparaison, comme d'autres le suggèrent. –

4

Utilisez une méthode d'extension pour vos Contient. Un exemple brillant a été trouvé here on stack overflow Le code n'est pas le mien, mais je l'afficherai ci-dessous.

public static bool Contains(this string source, string toCheck, StringComparison comp) 
{ 
    return source.IndexOf(toCheck, comp) >= 0; 
} 

string title = "STRING"; 
bool contains = title.Contains("string", StringComparison.OrdinalIgnoreCase); 
+0

Cela ne résout pas le problème - il veut voir si la ** collection ** de chaînes contient une chaîne particulière d'une manière insensible à la casse. Cela vérifie seulement si une ** chaîne ** contient une autre chaîne insensible à la casse. Vous devez avoir une méthode d'extension sur 'IEnumerable ', pas sur 'string'. – tvanfosson

+0

J'ai vu ta réponse, beaucoup mieux que la mienne. Honnêtement, je n'avais pas considéré l'aspect performance, et je ne connaissais pas le constructeur surchargé du HashSet. C'est toujours une belle extension à avoir, dans les deux cas! – StyxRiver

Questions connexes