2013-05-09 3 views
0

J'ai une liste d'éléments, appelée Traductions. Je filtre les traductions basées sur un terme de recherche d'une boîte de recherche, il ressemble actuellement à ceci:LINQ sélectionner un élément dans une liste où string contient l'un des termes de recherche dans une liste -> refactor

private static IList<Translation> FilterTranslationListOLD(string filter, IEnumerable<Translation> translationList) 
{ 
    filter = filter.ToLower(); 
    if (!string.IsNullOrEmpty(filter)) 
    { 

     return translationList 
      .Where(t => (t.Tag.Filename.ToLower().Contains(filter) 
          || t.Tag.FilePath.ToLower().Contains(filter) 
          || t.Tag.TagContent.ToLower().Contains(filter) 
          || (t.Tag.SanitizedTagContent != null && t.Tag.SanitizedTagContent.ToLower().Contains(filter)) 
          || (t.TagTranslation != null && t.TagTranslation.ToLower().Contains(filter)) 
          || (t.SanitizedTranslation != null && t.SanitizedTranslation.ToLower().Contains(filter)))) 
      .OrderBy(t => t.Tag.FilePath) 
      .ThenBy(t => t.Tag.Filename).ThenBy(t => t.Tag.Id).ToList(); 
    } 
    return translationList.OrderByDescending(t => t.DateTranslated).ToList(); 
} 

J'ai maintenant introduit la possibilité de rechercher avec plusieurs mots-clés, comme ceci:

private static IList<Translation> FilterTranslationList(string filter, IEnumerable<Translation> translationList) 
     { 
      filter = filter.ToLower(); 
      var splitFilterTerms = filter.Split(','); 

      if (splitFilterTerms.Any(split=>!string.IsNullOrEmpty(split))) 
      { 
       var translationListResults = new List<Translation>(); 
       foreach (var splitFilterTerm in splitFilterTerms) 
       { 
        translationListResults.AddRange(translationList 
        .Where(t => (t.Tag.Filename.ToLower().Contains(splitFilterTerm) 
            || t.Tag.FilePath.ToLower().Contains(splitFilterTerm) 
            || t.Tag.TagContent.ToLower().Contains(splitFilterTerm) 
            || (t.Tag.SanitizedTagContent != null && t.Tag.SanitizedTagContent.ToLower().Contains(splitFilterTerm)) 
            || (t.TagTranslation != null && t.TagTranslation.ToLower().Contains(splitFilterTerm)) 
            || (t.SanitizedTranslation != null && t.SanitizedTranslation.ToLower().Contains(splitFilterTerm)))) 
        .OrderBy(t => t.Tag.FilePath) 
        .ThenBy(t => t.Tag.Filename).ThenBy(t => t.Tag.Id).ToList()); 
       } 
       return translationListResults; 
      } 
      return translationList.OrderByDescending(t => t.DateTranslated).ToList(); 
     } 

Ce que je voudrais savoir, c'est s'il y a une meilleure façon d'écrire ça? Alors que cela fonctionne, il serait bon de savoir comment le faire dans tous les linq ou de le réduire/refactoriser un peu (en faire un peu plus propre). Merci d'avance!

Répondre

1

Essayez de regarder SelectMany, qui vous aidera à aplatir une séquence de séquences:

private static IList<Translation> FilterTranslationListOLD(string filter, IEnumerable<Translation> translationList) 
{ 
    filter = filter.ToLower(); 
    var splitFilterTerms = filter.Split(','); 
    if (splitFilterTerms.Any(split=>!string.IsNullOrEmpty(split))) 
    { 
     return splitFilterTerms.SelectMany(f => translationList 
      .Where(t => (t.Tag.Filename.ToLower().Contains(f) 
          || t.Tag.FilePath.ToLower().Contains(f) 
          || t.Tag.TagContent.ToLower().Contains(f) 
          || (t.Tag.SanitizedTagContent != null && t.Tag.SanitizedTagContent.ToLower().Contains(f)) 
          || (t.TagTranslation != null && t.TagTranslation.ToLower().Contains(f)) 
          || (t.SanitizedTranslation != null && t.SanitizedTranslation.ToLower().Contains(f)))) 
      .OrderBy(t => t.Tag.FilePath) 
      .ThenBy(t => t.Tag.Filename).ThenBy(t => t.Tag.Id)).ToList(); 
    } 
    return translationList.OrderByDescending(t => t.DateTranslated).ToList(); 
} 

Je ne l'ai pas fait exécuter ce code. Here is the MSDN documentation of SelectMany.

+0

Exactement ce que je cherchais. Garde tout dans linq et range un peu. Merci! Je trouve encore linq un peu difficile à lire parfois (pour comprendre immédiatement) mais je ne suis pas sûr si c'est un manque de familiarité ou parce que la syntaxe est très encombrée. –

+2

Si vous pensez qu'il est encombré, vous pouvez extraire l'argument entier à la clause 'Where' dans une variable de type' Func '. Cela pourrait rendre les choses plus ordonnées. –

0

Le problème avec le code ci-dessus est qu'il affiche en condition OU et non ET ... Donc, si vous avez ces éléments:

List<Car> Cars = new List<Car>(); 
Cars.Add(new Car(){Manufacturer="Mercedes Benz", Color="Blue"}); 
Cars.Add(new Car(){Manufacturer="Mercedes Benz", Color="Green"}); 

il affichera à la fois si le filtre est « Mercedes Bleu »

J'ai utilisé ce code pour montrer que la voiture bleue:

string Filter = "Mercedes blue"; 
List<string> SplittedFilter = new List<string>(Filter.ToLowerInvariant().Split(' ')); 

List<Car> FilteredCars = Cars; 

foreach (var item in SplittedFilter) { 
    FilteredCars = (from c in FilteredCars 
        where c.Manufacturer.ToLowerInvariant().Contains(item) || c.Color.ToLowerInvariant().Contains(item) 
        select c).ToList(); 

} 

Source: http://www.groggyjava.tv/blog/?p=84

Questions connexes