【问题标题】:C# advanced search in list列表中的 C# 高级搜索
【发布时间】:2021-04-09 17:06:17
【问题描述】:

我有包含两个项目的字符串内存列表:“product 1 max”和“product 1 min”。当用户输入为“product min”时,如何搜索并获取“product 1 min”?

请注意中间有一些遗漏的单词。

var list = new List<string> {"product 1 max", "product 1 min" };
//user input 'product min' and he expected 'product 1 min'

【问题讨论】:

  • 您是在使用 LINQ 查询数据库还是内存中的集合?
  • 内存中的集合
  • 看看这个库github.com/softwx/SoftWx.Match,它实现了 Damerau-Levenshtein 算法,计算两个字符串彼此之间的接近程度。
  • 我投票决定重新提出这个问题,因为它现在看起来已经足够清楚了。
  • 它现在重新开放,我投了赞成票。

标签: c# list linq search


【解决方案1】:

一种方法是拆分输入并将其与字符串列表中的每个单词进行匹配。

var list = new List<string> { "product 1 max", "product 1 min" };
var input = "product min";
List<string> inputParts = input.Split(' ').ToList();

// contains all the input strings
List<string> results = list.Where(x => x.Split(' ').Intersect(inputParts).Count() == inputParts.Count).ToList();

// partial matching strings
List<string> partialMatches = list.Where(x => x.Split(' ').Intersect(inputParts).Count() > 0).ToList();

Intersect 方法的文档可以是found here

【讨论】:

  • 您的变量 x 有错误我在尝试运行代码时收到此消息。 'string' 不包含'Intersect' 的定义,并且最佳扩展方法重载'Queryable.Intersect(IQueryable, IEnumerable)' 需要'IQueryable' 类型的接收器跨度>
  • @AbdussalamAshuaebi 在 x 之后也应该有一个 Split(),因为 Intersect 与两个 IEnumerables 一起使用。回复已更新
【解决方案2】:

一种实现方式是使用 Damerau-Levenshtein 算法。这是一种算法,它基本上计算一个字符串需要多少更改才能等于另一个,它可以手动实现,但有点棘手,并且已经有一个库 (SoftWx.Match) 为您封装了逻辑。

SoftWx.Match 有一个名为 DamerauOSA(string value1, string value2) 的静态方法,它返回一个介于 0 和 1 之间的 double,说明两个字符串的相似程度,您可以轻松地将其与 LINQ 混合。

List<string> products = new List<string>()
{
    "product 1 max",
    "product 1 min"
};
var stringToCompare = "product min";

products.ForEach(x => Console.WriteLine($"Item {x} against {stringToCompare} has {Similarity.DamerauOSA(x, stringToCompare)} points of similarity"));

// 0.80 is an arbitrary number of how much "equality" you want from both strings
var filtered = products.Where(x => Similarity.DamerauOSA(x, stringToCompare) > 0.80).ToList();

Console.WriteLine("Filtered");
filtered.ForEach(x => Console.WriteLine(x));

工作示例here

【讨论】:

    【解决方案3】:

    如果将输入拆分为单词,则可以将list 过滤为包含所有输入单词的匹配项:

    var inputWords = input.Split(' ');
    var ans = list.Where(s => inputWords.All(s.Contains)).ToList();
    

    注意:s.Contains 是一种更短、更高效(更晦涩)的方式来处理w =&gt; s.Contains(w)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-20
      • 2010-09-12
      • 1970-01-01
      相关资源
      最近更新 更多