Using IEqualityComparer for Union



我只想从两个列表中删除重复项并将它们合并到一个列表中。我还需要能够定义什么是重复项。我通过 ColumnIndex 属性定义一个重复项,如果它们相同,则它们是重复项。这是我采取的方法:

我找到了一个漂亮的示例,说明如何为随机场合编写内联比较器,其中在代码段中只需要一次。

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);
    }
}

然后我只有我的两个列表,并尝试与比较者合并。

            var formatIssues = issues.Where(i => i.IsFormatError == true);
            var groupIssues = issues.Where(i => i.IsGroupError == true);
            var dupComparer = new InlineComparer<Issue>((i1, i2) => i1.ColumnInfo.ColumnIndex == i2.ColumnInfo.ColumnIndex, 
            i => i.ColumnInfo.ColumnIndex);
            var filteredIssues = groupIssues.Union(formatIssues, dupComparer);

但是,结果集为空。

我误入歧途?我已经确认这两个列表具有相等的 ColumnIndex 属性的列。

我刚刚在测试集上运行了你的代码......它有效!

    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);
    }

那么......也许返回并检查您的测试数据 - 或者使用其他一些测试数据运行它?

毕竟 - 对于一个联盟是空的 - 这表明你的两个输入列表也是空的?

一个稍微简单的方法:

  • 它确实保留了原始顺序
  • 它会在发现欺骗时忽略它们

使用链接扩展方法:

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

这是MoreLinqDistinctBy lambda 方法

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;
        }
    }
}

Linq Except 方法不会为您执行此操作吗?

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);

相关内容

  • 没有找到相关文章

最新更新