Comparing two collections for equality irrespective of the order of items in them

后端 未结 19 1910
我在风中等你
我在风中等你 2020-11-22 10:28

I would like to compare two collections (in C#), but I\'m not sure of the best way to implement this efficiently.

I\'ve read the other thread about Enumerable.Sequen

19条回答
  •  遥遥无期
    2020-11-22 11:10

    Allowing for duplicates in the IEnumerable (if sets are not desirable\possible) and "ignoring order" you should be able to use a .GroupBy().

    I'm not an expert on the complexity measurements, but my rudimentary understanding is that this should be O(n). I understand O(n^2) as coming from performing an O(n) operation inside another O(n) operation like ListA.Where(a => ListB.Contains(a)).ToList(). Every item in ListB is evaluated for equality against each item in ListA.

    Like I said, my understanding on complexity is limited, so correct me on this if I'm wrong.

    public static bool IsSameAs(this IEnumerable source, IEnumerable target, Expression> keySelectorExpression)
        {
            // check the object
            if (source == null && target == null) return true;
            if (source == null || target == null) return false;
    
            var sourceList = source.ToList();
            var targetList = target.ToList();
    
            // check the list count :: { 1,1,1 } != { 1,1,1,1 }
            if (sourceList.Count != targetList.Count) return false;
    
            var keySelector = keySelectorExpression.Compile();
            var groupedSourceList = sourceList.GroupBy(keySelector).ToList();
            var groupedTargetList = targetList.GroupBy(keySelector).ToList();
    
            // check that the number of grouptings match :: { 1,1,2,3,4 } != { 1,1,2,3,4,5 }
            var groupCountIsSame = groupedSourceList.Count == groupedTargetList.Count;
            if (!groupCountIsSame) return false;
    
            // check that the count of each group in source has the same count in target :: for values { 1,1,2,3,4 } & { 1,1,1,2,3,4 }
            // key:count
            // { 1:2, 2:1, 3:1, 4:1 } != { 1:3, 2:1, 3:1, 4:1 }
            var countsMissmatch = groupedSourceList.Any(sourceGroup =>
                                                            {
                                                                var targetGroup = groupedTargetList.Single(y => y.Key.Equals(sourceGroup.Key));
                                                                return sourceGroup.Count() != targetGroup.Count();
                                                            });
            return !countsMissmatch;
        }
    

提交回复
热议问题