1

我想承认我在 LINQ 方面很弱。我有数据列表。我想按给定值搜索列表拳头,然后按最大出现次数对数据进行排序,这意味着行中的最大时间。

        List<SearchResult> list = new List<SearchResult>() { 
            new SearchResult(){ID=1,Title="Cat"},
            new SearchResult(){ID=2,Title="dog"},
            new SearchResult(){ID=3,Title="Tiger"},
            new SearchResult(){ID=4,Title="Cat"},
            new SearchResult(){ID=5,Title="cat"},
            new SearchResult(){ID=6,Title="dog"},
        };

如果我用“狗猫”之类的数据搜索和排序列表,那么输出将是

ID=1,Title=Cat
ID=4,Title=Cat
ID=5,Title=Cat
ID=2,Title=dog
ID=6,Title=dog

所有 cat 将首先出现,因为这个 cat 关键字在所有行中找到了最大时间,然后 dog 找到了最大时间。

以下数据不会出现,因为它不在搜索词中

ID=3,Title=Tiger

寻找解决方案。谢谢

更新部分代码

        List<SearchResult> list = new List<SearchResult>() { 
            new SearchResult(){ID=1,Title="Geo Prism 1995 - ABS #16213899"},
            new SearchResult(){ID=2,Title="Excavator JCB - ECU P/N: 728/35700"},
            new SearchResult(){ID=3,Title="Geo Prism 1995 - ABS #16213899"},
            new SearchResult(){ID=4,Title="JCB Excavator - ECU P/N: 728/35700"},
            new SearchResult(){ID=5,Title="Geo Prism 1995 - ABS #16213899"},
            new SearchResult(){ID=6,Title="dog"},
        };

        var to_search = new[] { "Geo", "JCB" };
        var result = list.Where(sr => to_search.Any(ts => String.Compare(ts, sr.Title, StringComparison.OrdinalIgnoreCase) == 0))
                         .GroupBy(sr => sr.Title.ToLower())
                         .OrderByDescending(g => g.Count());

        var matched = result.SelectMany(m => m);

        var completeList = matched.Concat(list.Except(matched));

        dataGridView2.DataSource = completeList.ToList();

我尝试在其他应用程序中使用您的逻辑,但它不起作用。根据逻辑,三行首先带有 GEO 关键字,然后接下来的 2 行带有 JCB,然后是无与伦比的其余部分。我需要在你的代码中改变什么。请帮忙。谢谢

4

3 回答 3

3

这将过滤您的列表并将其分组Title,按组的大小对组进行排序。

List<SearchResult> list = new List<SearchResult>() { 
    new SearchResult(){ID=1,Title="Cat"},
    new SearchResult(){ID=2,Title="dog"},
    new SearchResult(){ID=3,Title="Tiger"},
    new SearchResult(){ID=4,Title="Cat"},
    new SearchResult(){ID=5,Title="cat"},
    new SearchResult(){ID=6,Title="dog"},
};

var to_search = new[] { "cat", "dog" };

var result = list.Where(sr => to_search.Any(ts => String.Compare(ts, sr.Title, StringComparison.OrdinalIgnoreCase) == 0))
                 .GroupBy(sr => sr.Title.ToLower())
                 .OrderByDescending(g => g.Count());

foreach (var group in result)
    foreach (var element in group)
        Debug.WriteLine(String.Format("ID={0},Title={1}", element.ID, element.Title));

输出:

ID=1,Title=Cat
ID=4,Title=Cat
ID=5,Title=cat
ID=2,Title=dog
ID=6,Title=dog

如果您不关心实际的分组,可以使用SelectMany展平组列表。

(请注意,此代码将忽略 的大小写Title。我不知道这是您想要的还是代码中的拼写错误:您正在使用catand Cat,并且在您的输出中它只是Cat,但dog没有大写。)

编辑:

要获取不匹配的项目,您可以使用except

var unmatched = list.Except(result.SelectMany(m => m)); // beware! contains the tiger!

编辑2:

var result = list.Where(sr => to_search.Any(ts => String.Compare(ts, sr.Title, StringComparison.OrdinalIgnoreCase) == 0))
                 .GroupBy(sr => sr.Title.ToLower())
                 .OrderByDescending(g => g.Count());

var matched = result.SelectMany(m => m);

var completeList = matched.Concat(list.Except(matched));

foreach (var element in completeList)
    Debug.WriteLine(String.Format("ID={0},Title={1}", element.ID, element.Title));

输出

ID=1,Title=Cat
ID=4,Title=Cat
ID=5,Title=cat
ID=2,Title=dog
ID=6,Title=dog
ID=3,Title=Tiger

编辑 3

var result = from searchResult in list
             let key_string = to_search.FirstOrDefault(ts => searchResult.Title.ToLower().Contains(ts.ToLower()))
             group searchResult by key_string into Group
             orderby Group.Count() descending
             select Group;
于 2012-07-09T13:18:41.567 回答
1

我认为以下应该可以解决问题。

var searchText = "cat dog";
var searchResult = list
  .Select(i => new { 
       Item = i, 
       Count = list.Count(x => string.Compare(x.Title, i.Title, true) == 0)  // Add counter
  })
  .Where(i => searchText.Contains(i.Item.Title))
  .OrderByDescending(i => i.Count)
  .ThenBy(i => i.Item.ID)
  .ToList()

更新

如果最后想要不匹配的数据,则需要在匿名对象中添加另一个排序属性。

var searchText = "cat dog";
var searchResult = list
  .Select(i => new { 
       Item = i, 
       Matched = searchText.Contains(i.Item.Title.ToUpper()),
       Count = list.Count(x => string.Compare(x.Title, i.Title, true) == 0)  // Add counter
  })
  .OrderByDescending(i => i.Matched)
  .ThenBy(i => i.Count)
  .ThenBy(i => i.Item.ID)
  .ToList()
于 2012-07-09T13:17:56.953 回答
1
IEnumerable<string> pets = new[] { "Cat", "dog", "Tiger", "Cat", "cat", "dog" };
var test = pets
    .Where(p=>p.ToUpperInvariant() == "CAT" || p.ToUpperInvariant() == "DOG")
    .GroupBy(p => p.ToUpperInvariant())
    .OrderByDescending(g => g.Count())
    .SelectMany(p => p);

foreach (string pet in test)
    Console.WriteLine(pet);
于 2012-07-09T13:21:44.033 回答