2010-07-28 5 views
3

J'ai un List générique et je dois trouver une chaîne particulière dans cette liste. Pourriez-vous s'il vous plaît laissez-moi savoir quelle est la meilleure approche dans le ci-dessous?Lorsque vous recherchez un article dans une liste générique, dois-je utiliser LINQ ou Contient?

if (strlist.Contains("Test")) 
{ 
    // String found 
} 

ou

string res = (from d in strlist where d == "Test" select d).SingleOrDefault(); 

if (res == "Test") 
{ 
    //found 
} 

S'il vous plaît examiner la liste peut être très grande base de données de population. Vos pensées à ce sujet sont très appréciées.

+2

Obligatoire: Avez-vous testé et mesuré? – ChaosPandion

Répondre

5

Si vous avez List<string> (ou même IEnumerable<string>) et contient répond à vos besoins, utilisez Contient.

Si vous avez besoin de traitement supplémentaire qui contient ne fournit pas, je suggère d'utiliser Any():

if(strList.Any(s => s.StartsWith("Tes")) 
{ 
    // Found 
} 
+1

Exacaly, compilateur va faire ses optimisations de toute façon et l'extrait avec Contient semble beaucoup mieux;) –

2

Les deux méthodes se comportent différemment s'il y a plus d'un match; le premier retournera vrai et le second lancera une exception. Pour corriger cela, remplacez SingleOrDefault par FirstOrDefault.

Pour répondre à la question, vous devez appeler Contains si vous recherchez une correspondance exacte et Any si vous n'êtes pas.

Par exemple:

if (strings.Contains("SomeString", StringComparer.OrdinalIgnoreCase)) 

if (strings.Any(s => s.StartsWith("b")) 
+0

En fait, la seconde ne sera pas. Vous pensez 'Single'. – ChaosPandion

+0

@ChaosPandion: Incorrect. 'SingleOrDefault' ne retournera que' default (T) 's'il y a des correspondances _zero_. Sinon, il serait identique à 'FirstOrDefault'. – SLaks

+0

Je sais que vous ne devriez vraiment pas lire l'intention émotionnelle du texte mais aïe. – ChaosPandion

0

Vous devriez vraiment utiliser HashSet<string> comme la performance de Contains est nettement mieux. Maintenant, si vous devez utiliser une liste pour d'autres opérations, vous pouvez simplement avoir les deux disponibles.

var list = BuildListOfStrings(); 
var set = new HashSet<string>(list); 

if (set.Contains("Test")) 
{ 
    // ... 
} 

Maintenant vous avez la possibilité de trouver des articles dans l'ensemble comme une opération O(1).

test

static void Main(string[] args) 
{ 
    var lst = GenerateStrings().Take(5000000).ToList(); 
    var hsh = new HashSet<string>(lst); 
    var found = false; 
    var count = 100; 
    var sw = Stopwatch.StartNew(); 

    for (int i = 0; i < count; i++) 
    { 
     hsh = new HashSet<string>(lst); 
    } 
    Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks/count)); 

    sw = Stopwatch.StartNew(); 
    for (int i = 0; i < count; i++) 
    { 
     found = lst.Contains("12345678"); 
    } 
    Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks/count)); 

    sw = Stopwatch.StartNew(); 
    for (int i = 0; i < count; i++) 
    { 
     found = hsh.Contains("12345678"); 
    } 
    Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks/count)); 

    Console.WriteLine(found); 
    Console.ReadLine(); 
} 

private static IEnumerable<string> GenerateStrings() 
{ 
    var rnd = new Random(); 
    while (true) 
    { 
     yield return rnd.Next().ToString(); 
    } 
} 

Résultat

 
0.308438 s 
0.0197868 s 
0.0 s 

Alors qu'est-ce que cela nous dit? Si vous effectuez une petite quantité d'appels à Contains, utilisez un List<string>, sinon utilisez un HashSet<string>.

+1

S'il a besoin de conserver la commande, il ne devrait pas. – SLaks

+0

@SLaks - Vous avez évidemment raison, mais le fait qu'ils mentionnent que la liste peut être très grande signifie que cela améliorera considérablement les performances.Puisque 'string' est un type de référence, ils peuvent simplement garder un' List 'pour d'autres opérations et ne pas avoir à s'inquiéter de l'utilisation excessive de la mémoire. – ChaosPandion

+1

Cela suppose que le contenu de la liste est fixe et cette tâche est répétée. Construire un hashSet ad hoc juste pour effectuer un Contain, ralentira, alors il suffit d'appeler Contient sur une liste, –

Questions connexes