LINQ从列表中选择项目,其中字符串包含列表中的任何搜索项 - >重构

时间:2013-05-09 11:18:20

标签: linq refactoring

我有项目列表,称为翻译。我根据搜索框中的搜索词过滤翻译,目前看起来像这样:

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

我现在已经介绍了使用多个关键字进行搜索的功能,例如:

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

我想知道的是,有更好的方式来写这个吗?虽然它可以工作,但是知道如何在所有linq中执行它或者稍微减少/重构它(使它有点整洁)会很好。提前谢谢!

2 个答案:

答案 0 :(得分:1)

尝试查看SelectMany,这将帮助您压缩一系列序列:

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

我实际上没有运行此代码。 Here is the MSDN documentation of SelectMany

答案 1 :(得分:0)

上面代码的问题是它显示在OR状态而不是AND ... 所以,如果你有这些项目:

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

如果过滤器是“Mercedes Blue”

,它将显示两者

我使用此代码仅显示蓝色汽车:

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();

}

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