LINQ OrderBy:结果列表顶部的最佳搜索结果

时间:2010-05-19 17:57:32

标签: linq sorting linq-to-objects

考虑是否需要按名字和姓氏搜索Customer列表。希望结果列表由客户按搜索条件中的最匹配排序。

FirstName      LastName
----------     ---------
Foo            Laurie
Bar            Jackson
Jackson        Bro
Laurie         Foo
Jackson        Laurie
string[] searchTerms = new string[] {"Jackson", "Laurie"};

//want to find those customers with first, last or BOTH names in the searchTerms
var matchingCusts = Customers
                       .Where(m => searchTerms.Contains(m.FirstName)
                               ||  searchTerms.Contains(m.LastName))
                       .ToList();

/* Want to sort for those results with BOTH FirstName and LastName 
   matching in the search terms. Those that match on both First and Last
   should  be at the top of the results, the rest who match on 
   one property should be below.
*/

 return matchingCusts.OrderBy(m=>m); 

所需排序:

Jackson        Laurie  (matches on both properties)
Foo            Laurie
Bar            Jackson
Jackson        Bro
Laurie         Foo

如何使用LINQ和OrderBy / OrderByDescending实现所需的功能?

3 个答案:

答案 0 :(得分:10)

使用Select与客户进行“匹配评估”,然后按顺序进行排序:

class Program
{
    static void Main(string[] args)
    {
        var Customers = new Customer[]
        {
            new Customer { FirstName = "Foo", LastName = "Laurie" },
            new Customer { FirstName = "Bar", LastName = "Jackson" },
            new Customer { FirstName = "Jackson", LastName = "Bro" },
            new Customer { FirstName = "Laurie", LastName = "Foo" },
            new Customer { FirstName = "Jackson", LastName = "Laurie" },
        };

        string[] searchTerms = new string[] { "Jackson", "Laurie" };

        //want to find those customers with first, last or BOTH names in the searchTerms 
        var matchingCusts = Customers
                               .Where(m => searchTerms.Contains(m.FirstName)
                                       || searchTerms.Contains(m.LastName))
                               .ToList();

        var result = matchingCusts.Select(x => new
            {
                Customer = x,
                MatchEvaluation = (searchTerms.Contains(x.FirstName) ? 1 : 0) + (searchTerms.Contains(x.LastName) ? 1 : 0),
            })
            .OrderByDescending(x => x.MatchEvaluation)
            .Select(x => x.Customer);

        foreach (var c in result)
        {
            Console.WriteLine(c.FirstName + " " + c.LastName);
        }

        Console.ReadKey();
    }

    public sealed class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}

答案 1 :(得分:5)

因为我完全错过了原来的问题:

一个班轮:)

var matchingCusts = Customers
    .Where(m => searchTerms.Contains(m.FirstName) ||
                searchTerms.Contains(m.LastName))
    .Select(c => new
    {
        Customer = c,
        Sort = ((searchTerms.Contains(c.FirstName) ? 0 : 1) + 
                (searchTerms.Contains(c.LastName) ? 0 : 1))
    })
    .OrderBy(o => o.Sort)
    .ThenBy(o1 => o1.Customer.LastName)
    .ThenBy(o2 => o2.Customer.FirstName)
    .Select(r => r.Customer);

答案 2 :(得分:0)

您可以让自己的IEqualityComparer<Customer>传递给orderby函数。

使构造函数获取searchTerms列表,然后按字母顺序排列包含优先级。

然后执行.SortBy(c => c.LastName, new MyEqualityComparer(searchTerms)).ThenBy(c => c.FirstName, new MyEqualityComparer(searchTerms))