C# - 将2个列表与自定义元素进行比较

Nha*_*ran 1 c# iterator for-loop list

我有2个清单.一个包含搜索元素,一个包含数据.我需要为list2中的每个元素循环,其中包含list1中的任何字符串("cat"或"dog").举些例子:

List<string> list1 = new List<string>();
list1.Add("Cat");
list1.Add("Dog");
list1.Add... ~1000 items;

List<string> list2 = new List<string>();
list2.Add("Gray Cat");
list2.Add("Black Cat");
list2.Add("Green Duck");
list2.Add("White Horse");
list2.Add("Yellow Dog Tasmania");
list2.Add("White Horse");
list2.Add... ~million items;
Run Code Online (Sandbox Code Playgroud)

我的期望是listResult: {"Gray Cat", "Black Cat", "Yellow Dog Tasmania"}(因为它在list1中包含"cat"和"dog").而不是嵌套循环,你有任何想法让序列运行得更快吗?

我目前的解决方案如下.但是......看起来太慢了:

foreach (string str1 in list1)
{
   foreach (string str2 in list2)
   {
      if str2.Contains(str1)
      {
         listResult.Add(str2);
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

fub*_*ubo 6

并行化的一个很好的用例!

没有并行化的Linq方法(在内部等于你的方法除了内部循环在找到一个匹配时中断的事实 - 你的方法也搜索其他匹配)

List<string> listResult = list2.Where(x => list1.Any(x.Contains)).ToList();
Run Code Online (Sandbox Code Playgroud)

将循环并行化AsParallel()- 如果你有一个多核系统,将会有巨大的性能提升.

List<string> listResult = list2.AsParallel().Where(x => list1.Any(x.Contains)).ToList();
Run Code Online (Sandbox Code Playgroud)

运行时比较:(4核心系统,list1 1000项,list2 1.000.000项)

Without AsParallel(): 91 seconds
With    AsParallel(): 23 seconds
Run Code Online (Sandbox Code Playgroud)

另一种方式Parallel.ForEach和线程安全结果列表

System.Collections.Concurrent.ConcurrentBag<string> listResult = new System.Collections.Concurrent.ConcurrentBag<string>();
System.Threading.Tasks.Parallel.ForEach<string>(list2, str2 =>
{
    foreach (string str1 in list1)
    {
        if (str2.Contains(str1))
        {
            listResult.Add(str2);
            //break the loop if one match was found to avoid duplicates and improve performance
            break;
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

旁注:你必须首先break;在匹配后迭代list2 ,否则你要两次添加项目:https://dotnetfiddle.net/VxoRUW

  • 它更快,因为它不需要`list1`的完整循环,并且还修复了如果有多个匹配则OP多次添加相同元素的错误. (3认同)