【问题标题】:Is there a way to get the difference between two sets of objects in c#有没有办法在c#中获得两组对象之间的差异
【发布时间】:2010-10-22 19:29:43
【问题描述】:

我想得到 c# 中两组 int 之间的差异。给定 s1 和 s2 我想返回那些在 s1 中而不是在 s2 中的整数。我可以这样做:

    List<int> s1 = new List<int>();
    List<int> s2 = new List<int>();

    foreach (int i in s1)
    {
        if (s1.Contains(i))
        {
            //
        }
        else
        {
            //
        }
    }

但我想知道是否有人可以指出更清洁的东西。我想做一些诸如

之类的事情
List<int> omitted = s1.Difference(s2);

不确定是否存在任何人都可以指出的现有方法或 LINQ 构造?谢谢。

【问题讨论】:

    标签: c# .net linq hashset


    【解决方案1】:
    IEnumerable<T> a, b;
    
    var added = a.Except(b);
    var removed = b.Except(a);
    

    【讨论】:

    • 注意这里使用的是Enumerable.Except,所以需要使用System.Linq。 msdn.microsoft.com/en-us/library/bb300779.aspx
    • 有问题吗?不,我只是想帮助那些可能剪切并粘贴此代码并发现它无法编译的人。
    • @Brian,同样的警告也适用于您自己的答案。 HashSet 没有实现它自己的 except 方法,所以你的答案也需要 System.Linq。
    • @Deviant:但你的运行时间为 O(n^2),而我的运行时间为 O(n) :)
    • 这个答案表明您必须调用 except 两次才能同时获得添加和删除的项目。这一点很容易错过。
    【解决方案2】:

    我想你想要HashSet.Except。也就是不使用Lists,使用HashSets,然后操作就可以了。如果您所代表的内容确实是一个“集合”,那么这是一种更好的类型。 (如果您已经有一个列表,您可以从中创建一个“新 HashSet”。)

    【讨论】:

    • 太棒了,谢谢。 except() 是我一直在寻找的方法,我接受你对 HashSets 的建议。
    • 除了是扩展功能,不是吗?
    • 有一个扩展方法Enumerable。除了所有的IEnumerables。但是 HashSet 有一个方法 except 专门用于 HashSets。
    • Except 确实是一种可对任何 IEnumerable 进行操作的扩展方法(请参阅msdn.microsoft.com/en-us/library/…)。这意味着它在 List 上运行良好。当然,如果顺序无关紧要,HashSet /is/ 是更合适的类型。
    • 布赖恩,我不这么认为。您上面链接的方法是扩展方法。 HashSet有一个ExceptWith方法,破坏性地从实例HashSet中移除参数中的元素,但没有Except。
    【解决方案3】:
    List<int> s1 = new List<int>();
    List<int> s2 = new List<int>();
    
    return sl.FindAll( i => !s2.Contains(i) )
    

    【讨论】:

      【解决方案4】:

      另一个有用的API,获取对称差:

      HashSet.SymmetricExceptWith()

      【讨论】:

        【解决方案5】:
        来自 s1 中的 x 在哪里 ! s2.包含(x) 选择 x

        【讨论】:

          【解决方案6】:

          当您需要查找两个 IEnumerable 之间的无序差异时,这两种扩展方法可能会派上用场(它或多或少与 leppie wrapper 对扩展方法给出的答案相同):

          public class EnumerableDifferences<T>
          {
              public IEnumerable<T> Added { get; }
              public IEnumerable<T> Removed { get; }
          
              public EnumerableDifferences(IEnumerable<T> added, IEnumerable<T> removed)
              {
                  Added = added;
                  Removed = removed;
              }
          }
          
          public static class EnumerableExtensions
          {
              public static HashSet<TSource> ToHashSet<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
              {
                  return new HashSet<TSource>(source, comparer);
              }
          
              public static IEnumerable<TSource> ExceptBy<TSource, TKey>(this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer = null)
              {
                  return first
                      .ExceptBy(keySelector, second.Select(keySelector), keyComparer);
              }
          
              public static IEnumerable<TSource> ExceptBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEnumerable<TKey> keys, IEqualityComparer<TKey> keyComparer = null)
              {
                  var secondKeys = keys.ToHashSet(keyComparer);
          
                  foreach (var firstItem in source)
                  {
                      var firstItemKey = keySelector(firstItem);
          
                      if (!secondKeys.Contains(firstItemKey))
                      {
                          yield return firstItem;
                      }
                  }
              }
          
              public static EnumerableDifferences<TSource> DifferencesBy<TSource, TKey>(this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer = null)
              {
                  keyComparer = keyComparer ?? EqualityComparer<TKey>.Default;
          
                  var removed = first.ExceptBy(second, keySelector, keyComparer);
                  var added = second.ExceptBy(first, keySelector, keyComparer);
          
                  var result = new EnumerableDifferences<TSource>(added, removed);
          
                  return result;
              }
          
              public static EnumerableDifferences<TSource> Differences<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer = null)
              {
                  return first
                      .DifferencesBy(second, x => x, comparer);
              }
          }
          
          public static class Program
          {
              public static void Main(params string[] args)
              {
                  var l1 = new[] { 'a', 'b', 'c' };
                  var l2 = new[] { 'a', 'd', 'c' };
          
                  var result = l1.Differences(l2);
          
                  Console.ReadKey();
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-12-01
            • 2015-07-22
            • 1970-01-01
            • 2021-05-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多