代码之家  ›  专栏  ›  技术社区  ›  driis

linq:确定两个序列是否包含完全相同的元素

  •  62
  • driis  · 技术社区  · 15 年前

    我需要确定两个集合是否包含完全相同的元素。顺序无关紧要。

    例如,这两个数组应视为相等:

    IEnumerable<int> data = new []{3, 5, 6, 9};
    IEnumerable<int> otherData = new []{6, 5, 9, 3}
    

    一个集合不能包含不在另一个集合中的任何元素。

    是否可以使用内置的查询运算符来完成此操作?考虑到元素的数量可能从几个到数百个不等,那么实现它的最有效方法是什么?

    7 回复  |  直到 6 年前
        1
  •  109
  •   Mehrdad Afshari    10 年前

    如果要将数组视为“集合”,忽略顺序和重复项,则可以使用 HashSet<T>.SetEquals method 以下内容:

    var isEqual = new HashSet<int>(first).SetEquals(second);
    

    否则,您的最佳选择可能是以相同的方式对两个序列进行排序并使用 SequenceEqual 比较一下。

        2
  •  44
  •   Joren    15 年前

    我建议对两者进行排序,并进行逐元素比较。

    data.OrderBy(x => x).SequenceEqual(otherData.OrderBy(x => x))
    

    我不确定 OrderBy 是的,但是如果它是O(n log n)类型,就像您期望的那样,那么总的算法也是O(n log n)。

    对于某些情况下的数据,可以通过使用orderby的自定义实现来改进这一点,例如,使用计数排序(对于o(n+k),其中k是值所在范围的大小。

        3
  •  3
  •   Justin Grant    15 年前

    如果您可能有重复项(或者如果您想要一个更适合长列表的解决方案),我将尝试如下操作:

    static bool IsSame<T>(IEnumerable<T> set1, IEnumerable<T> set2)
    {
        if (set1 == null && set2 == null)
            return true;
        if (set1 == null || set2 == null)
            return false;
    
        List<T> list1 = set1.ToList();
        List<T> list2 = set2.ToList();
    
        if (list1.Count != list2.Count)
            return false;
    
        list1.Sort();
        list2.Sort();
    
        return list1.SequenceEqual(list2);
    }
    

    更新:哎呀,你们是对的——下面的except()解决方案需要在过街之前双向查看。而且它在长的列表中表现不佳。忽略下面的建议!-)

    这是一个简单的方法。请注意,这假定列表没有重复项。

    bool same = data.Except (otherData).Count() == 0;
    
        4
  •  2
  •   Peter Mortensen venu    6 年前

    另一种方法是:

    IEnumerable<int> data = new[] { 3, 5, 6, 9 };
    IEnumerable<int> otherData = new[] { 6, 5, 9, 3 };
    
    data = data.OrderBy(d => d);
    otherData = otherData.OrderBy(d => d);
    data.Zip(otherData, (x, y) => Tuple.Create(x, y)).All(d => d.Item1 == d.Item2);
    
        5
  •  0
  •   Kobi    15 年前
    1. 首先,检查长度。如果它们是不同的,那么集合是不同的。
    2. 你可以做到 data.Intersect(otherData); ,检查长度是否一致。
    3. 或者,对集合进行简单排序,并对它们进行迭代。
        6
  •  -1
  •   Blounty    15 年前

    这将有助于:

        IEnumerable<int> data = new []{ 3,5,6,9 };
        IEnumerable<int> otherData = new[] {6, 5, 9, 3};
    
        if(data.All(x => otherData.Contains(x)))
        {
            //Code Goes Here
        }
    
        7
  •  -1
  •   nunoalmeida    10 年前

    首先检查两个数据集合中的元素数量是否相同,并检查一个集合中的所有元素是否都显示在另一个集合中

            IEnumerable<int> data = new[] { 3, 5, 6, 9 };
            IEnumerable<int> otherData = new[] { 6, 5, 9, 3 };
    
            bool equals = data.Count() == otherData.Count() && data.All(x => otherData.Contains(x));