查找最具体的匹配项

时间:2016-08-03 14:02:20

标签: c# linq

用户输入将类似于BY1 2PX',它将分割并存储到如下列表中

var items = new List<string> {'BY1 2PX', 'BY12', 'BY1', 'BY'};

我有产品来源列表

public class Product
{
    public string Name {get;set;}
    public string Id {get;set;}
}

以下是示例产品列表。订购时没有保证,可以是任何顺序。

var products = new List<Product>{ 
    new Product("1", "BY1 2PX"),
    new Product("2", "BY12"),
    new Product("3", "BY1"),
    new Product("4", "BY"),
    new Product("5", "AA2 B2X"),
    //...etc
}

我的输出应该获取1,因为它最具体的匹配。如果Id = 1不存在那么它应该已经获取了Id = 2,就像那样......等任何人都可以帮我写一个linq查询。我尝试过类似下面的东西,这很好吗?

var result =  items.Select(x => products.FirstOrDefault(p =>
                      string.Equals(p.Name.Trim(), x, StringComparison.OrdinalIgnoreCase)))
                   .FirstOrDefault();

4 个答案:

答案 0 :(得分:2)

好吧,你可以使用字典及其快速查找:

var productsDict = products.ToDictionary(p => p.Name, p => p);

var key = items.FirstOrDefault(i => productsDict.ContainsKey(i));

Product result = key != null ? productsDict[key] : null;

或者Tim建议,如果你有多个具有相同名称的元素,你可以使用Lookup:

var productsDict = products.ToLookup(p => p.Name, p => p);

var key = items.FirstOrDefault(i => productsDict.Contains(i));

Product result = key != null ? productsDict[key] : null;

答案 1 :(得分:1)

如果您想选择最匹配的产品,您需要从产品中选择 - 而不是字符串列表。您可以使用以下使用List.FindIndex的LINQ方法:

Product bestProduct = products
    .Select(p => new {
        Product = p,
        Index = items.FindIndex(s => String.Equals(p.Name, s, StringComparison.OrdinalIgnoreCase))
     })
    .Where(x => x.Index != -1)
    .OrderBy(x => x.Index)   // ensures the best-match logic
    .Select(x => x.Product)
    .FirstOrDefault();

如果没有匹配的产品,Where可确保您不会获得任意产品。

<强>更新

此查询提供了更有效的解决方案:

Product bestProduct = items
    .Select(item => products.FirstOrDefault(p => String.Equals(p.Name, item, StringComparison.OrdinalIgnoreCase)))
    .FirstOrDefault(p != null);   // ensures the best-match logic

答案 2 :(得分:0)

你可以尝试通过使用一个名为Levenshtein's distance algorythm的特定算法找到单词的相似性,这个词主要用于&#34;你的意思是&#39; word&#39;&#34;在大多数搜索网站上。

此解决方案可在此处找到: https://stackoverflow.com/a/9453762/1372750

找到距离差异后,您可以衡量哪个词或短语更多&#34;喜欢&#34;搜索到的那个。

答案 3 :(得分:0)

这将为每个产品找到项目中“最具体”(最长)匹配的内容,并返回最长匹配的产品(无论是哪个系列的订单)

var result = products
            .Select(p => new
                {
                    Product = p,
                    MostSpecific = items.Where(item => p.Name.Contains(item))
                                        .OrderByDescending(match => match.Length
                                        .FirstOrDefault()
                })
            .Where(x => x.MostSpecific != null)
            .OrderByDescending(x => x.MostSpecific.Length)
            .Select(x => x.Product)
            .FirstOrDefault();