在列表中首先选择具有特定元素的列表的子集

时间:2009-08-11 02:51:17

标签: c# linq

我在供应商的C#中有一个列表,它们都有一个Name属性。我想允许用户通过搜索名称来过滤该列表。过滤字符串可以是部分匹配或完全匹配。但是,如果结果列表包含完全匹配,则它应该在列表中的位置为零,之后将包含所有部分匹配。

我可以很容易地使用linq和lambdas获取子列表但是我不得不求助于创建第二个列表,如果存在完全匹配,添加它,然后添加其余的匹配而不使用确切的一个。感觉不够优雅。有没有更简单的方法?我当前的代码(从内存完成,因此可能无法编译):

List<Vendor> temp = vendors.Where(v => v.Name.ToUpper().Contains(vendorNameSearch)).ToList();
Vendor exactMatch = vendors.Single(v => v.Name.ToUpper().Equals(vendorNameSearch));

if(null == exactMatch){return temp;}
else
{
    List<Vendor> temp1 = new List<Vendor>();
    temp1.Add(exactMatch);
    temp1.AddRange(temp.Remove(exactMatch));
    return temp1;
}

4 个答案:

答案 0 :(得分:3)

开发一个计算Levenshtein距离的StringComparer如何 - 对于精确匹配应该为零 - 并按升序对结果进行排序。这样,您首先得到完全匹配,其余结果按搜索字符串的相似性(至少一个度量)排序。

var list = vendors.Where( v => v.Name.ToUpper().Contains( vendorNameSearch ) )
                  .OrderBy( v => ComputeLevenshtein( v.Name.ToUpper(),
                                                     vendorNameSearch ) );

或者你可以制作一个比较器来命令具有完全匹配的东西为int.MinValue,而所有其他值都是CompareTo()的结果。这也将首先排序完全匹配。

答案 1 :(得分:3)

首先,我喜欢tvanfosson从可用性角度回答的方法。

否则,您可以使用复合排序实现所需的行为:

vendors.Where(v => v.Name.ToUpper().Contains(vendorNameSearch))
       .OrderBy(v => !string.Equals(v.Name, vendorNameSearch))
       .ThenBy(v => v.Name)
       .ToList();

按照完全匹配比较的布尔结果排序将确保首先列出完全匹配。由于布尔值的排序方式,具有精确名称匹配的供应商应具有值false。您也可以使用OrderByDescending实现此目的,而不是反转字符串相等。

答案 2 :(得分:1)

我不知道这有多高效,但这是另一种选择,

List<String> strings = new List<String> {"Cat","Dog","Pear","Apple","Catalog"};

var results = (from st in strings
    where st == "Cat"
    select new {Priority = 1,st}).Union(

    from st in strings
    where st.Contains("Cat")
    select new {Priority = 2, st}).OrderBy(x => x.Priority).Select(x=> x.st).Distinct();

答案 3 :(得分:1)

按字符串长度的绝对差异排序。完全匹配将是唯一具有相同长度的匹配(绝对差异= 0),而其他匹配将全部大于0:

var list = vendors.Where(v => v.Name.ToUpper().Contains(vendorNameSearch))
                  .OrderBy(v => Math.Abs(v.Name.ToUpper().Length - vendorNameSearch.Length)));

这将是一个任意的顺序,但它实现了你的主要目标。

但是,当然,像原始代码这样的两步解决方案没有任何问题,如果能够完成这项工作的话。