用户输入将类似于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();
答案 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();