c# - 具有非唯一条目的两个列表之间的差异

标签 c# linq

我有两个列表。一个代表我的代码可以运行的函数类型,另一个代表将运行这些函数的代理。这两个列表应该是一对一的关系,但是当远程服务请求更多功能时,我需要找出这两个列表之间的区别。 问题是条目不是唯一的,因此我不能只调用 list1.RemoveAll(list2) 因为这会删除 List2 中包含的具有相同值的所有条目,而不是每个条目仅删除一个条目.

这就是我需要的:

{a,a,a,a,b,b,c} - {a,a,b,c} = {a,a,b}

这就是我现在的做法:

var difference = list1.ToList();
foreach (var entry in list2)
{
    difference.Remove(entry);
}

它很实用并且可以完成工作,但它破坏了我在其余代码中的 Linq 用法。

我尝试找出一种方法并在网上搜索,但找不到使用 Linq 来执行此操作的方法。

最佳答案

对于集合(序列),嵌套循环和Remove可能无效(从O (N * M)O(N * N * M)) 您可以尝试用 O (N + M) 时间进行分组字典复杂。请注意,该实现不保持初始顺序({a, b, b, a} - {b} == {a, a, b},而不是 {a, b, a}):

List<char> left = new List<char>() { 'a', 'a', 'a', 'a', 'b', 'b', 'c' };
List<char> right = new List<char>() { 'a', 'a', 'b', 'c' };

var counts = right
  .GroupBy(item => item)
  .ToDictionary(chunk => chunk.Key, chunk => chunk.Count());

var difference = left
  .GroupBy(item => item)
  .SelectMany(chunk => chunk.Skip(counts.TryGetValue(chunk.Key, out var skip) ? skip : 0))
  .ToList();

编辑:创建基准很容易;基准;如果序列较长 (N = 200000),则以 hash(GroupByDictionary)为准;确保如果您没有那么长的集合,您可以安全地保留初始代码:

Random rnd = new Random(1);

int N = 200000;

List<char> left = Enumerable
  .Range(0, N)
  .Select(index => (char)(rnd.Next('z' - 'a') + 'a'))
  .ToList();

List<char> right = Enumerable
  .Range(0, N)
  .Select(index => (char)(rnd.Next('z' - 'a') + 'a'))
  .ToList();

现在让马跑:

Stopwatch watch = new Stopwatch();

watch.Start();

// Hash solution
var counts = right
  .GroupBy(item => item)
  .ToDictionary(chunk => chunk.Key, chunk => chunk.Count());

var result = left
  .GroupBy(item => item)
  .SelectMany(chunk => chunk.Skip(counts.TryGetValue(chunk.Key, out var skip) ? skip : 0))
  .ToList();

watch.Stop();

TimeSpan tHash = watch.Elapsed;

watch.Reset();
watch.Start();

// Initial solution
var difference = left.ToList();

foreach (var entry in right) {
  difference.Remove(entry);
}

watch.Stop();

TimeSpan tInitial = watch.Elapsed;

Console.Write($"Hash: {tHash}; Initial {tInitial}");

结果(酷睿 i7 3.6GHz)11 毫秒1.4 秒

  Hash: 00:00:00.0111296; Initial 00:00:01.3957468

关于c# - 具有非唯一条目的两个列表之间的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52474648/

相关文章:

c# - 根据其名称的字符串调用属性

c# - 在 .NET 中捕获存储过程打印输出

c# - 在 ASP.NET Web API 中处理 ModelState 验证

c# - 使用 Moq 模拟不安全的接口(interface)

c# - 将两个无限的 C# IEnumerables 连接在一起,没有特定的顺序

c# - 使用 linq 按逗号分隔的列值按相关性排序数据表

C# - System.FormatException 类型的未处理异常 - 列出字符串以列出 int

c# - "OR"按需使用 Linq to Entities,我该怎么做?

c# - MVC LINQ,其中 UserID 等于经过身份验证的用户

linq - C# EF5 Code First 中多对多关系的 Lambda 表达式