Using IEqualityComparer for Union

前端 未结 3 1849
遇见更好的自我
遇见更好的自我 2020-12-17 16:17

I simply want to remove duplicates from two lists and combine them into one list. I also need to be able to define what a duplicate is. I define a duplicate by the ColumnInd

相关标签:
3条回答
  • 2020-12-17 16:50

    Would the Linq Except method not do it for you?

    var formatIssues = issues.Where(i => i.IsFormatError == true);
    var groupIssues = issues.Where(i => i.IsGroupError == true);
    
    var dupeIssues = issues.Where(i => issues.Except(new List<Issue> {i})
                                            .Any(x => x.ColumnIndex == i.ColumnIndex));
    
    var filteredIssues = formatIssues.Union(groupIssues).Except(dupeIssues);
    
    0 讨论(0)
  • 2020-12-17 16:54

    I've just run your code on a test set.... and it works!

        public class InlineComparer<T> : IEqualityComparer<T>
        {
            private readonly Func<T, T, bool> getEquals;
            private readonly Func<T, int> getHashCode;
    
            public InlineComparer(Func<T, T, bool> equals, Func<T, int> hashCode)
            {
                getEquals = equals;
                getHashCode = hashCode;
            }
    
            public bool Equals(T x, T y)
            {
                return getEquals(x, y);
            }
    
            public int GetHashCode(T obj)
            {
                return getHashCode(obj);
            }
        }
    
        class TestClass
        {
            public string S { get; set; }
        }
    
        [TestMethod]
        public void testThis()
        {
            var l1 = new List<TestClass>()
                         {
                             new TestClass() {S = "one"},
                             new TestClass() {S = "two"},
                         };
            var l2 = new List<TestClass>()
                         {
                             new TestClass() {S = "three"},
                             new TestClass() {S = "two"},
                         };
    
            var dupComparer = new InlineComparer<TestClass>((i1, i2) => i1.S == i2.S, i => i.S.GetHashCode());
    
            var unionList = l1.Union(l2, dupComparer);
    
            Assert.AreEqual(3, unionList);
        }
    

    So... maybe go back and check your test data - or run it with some other test data?

    After all - for a Union to be empty - that suggests that both your input lists are also empty?

    0 讨论(0)
  • 2020-12-17 16:56

    A slightly simpler way:

    • it does preserve the original order
    • it ignores dupes as it finds them

    Uses a link extension method:

       formatIssues.Union(groupIssues).DistinctBy(x => x.ColumnIndex)
    

    This is the DistinctBy lambda method from MoreLinq

    public static IEnumerable<TSource> DistinctBy<TSource, TKey>
         (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
    {
        HashSet<TKey> knownKeys = new HashSet<TKey>();
        foreach (TSource element in source)
        {
            if (knownKeys.Add(keySelector(element)))
            {
                yield return element;
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题