从另一个列表中删除列表项

时间:2018-10-24 23:55:38

标签: c# .net collections

我有一个包含一些元素的列表,我想从另一个列表中删除元素。 如果某项的值Contain(不等于)另一个列表中的值,则应将其删除。

其中一种方法是执行此操作:

var MyList = new List<string> { ... }
var ToRemove = new List<string> { ... }
MyList.RemoveAll(_ => ToRemove.Any(_.Contains));

有效...

但是,我有很多个列表(> 1百万个),并且由于可以对ToRemove进行排序,因此使用它来加快处理速度是很有意义的。

创建一个循环可以很容易地做到这一点,但是有一种方法可以对已排序的集合执行此操作?


更新:

在包含禁止列表的文本上进行20k次迭代后,我得到了:

  

禁止列表作为列表-> 00:00:07.1993364

     

禁止列表作为HashSet-> 00:00:07.9749997

多次运行后保持一致,因此哈希集较慢

2 个答案:

答案 0 :(得分:1)

由于二进制搜索ToRemove的复杂性,您可能需要对O(log n)进行排序(您需要重写_ => ToRemove.Any(_.Contains))。

但是,相反,对HashSet<string>使用List<string>而不是ToRemove会更快,因为在哈希集中查找元素(使用Contains)是{{ 1}}操作。

另外,将O(1)用于LinkedList<string>可能会有所益处,因为由于数组大小的调整,从链接列表中删除项目通常比从基于数组的列表中删除要快。

答案 1 :(得分:1)

由于这是删除包含另一个列表中的字符串的字符串,所以HashSet不会有太大帮助。实际上,除非您要查找完全匹配的内容或维护所有子字符串的索引(否则,这很昂贵),而昂贵的AFIK仅SQL Server在BigData领域之外半有效地做到这一点。 如果您关心的只是它以“ ToRemove”中的项目开头,则排序可能会有所帮助。在“ ToRemove”自定义二进制搜索中对“ MyList”和foreach字符串进行排序,以找到以该字符串和RemoveAt索引开头的任何字符串,直到没有开头为止,然后再递减索引,直到没有开头为止。