【问题标题】:C# Compare Two Lists of Different Objects [duplicate]C#比较不同对象的两个列表[重复]
【发布时间】:2015-04-09 22:38:13
【问题描述】:

我看到了Quickest way to compare two List<>,但我无法适应我的情况。我的问题是列表的类型不同。

我的列表是这样的:

List<Type1> firstList;
List<Type2> secondList;

这是我现在拥有的:

foreach (Type1 item in firstList)
{
    if (!secondList.Any(x => x.Id == item.Id))
    {
        // this code is executed on each item in firstList but not in secondList
    }
}
foreach (Type2 item in secondList)
{
    if (!firstList.Any(x => x.Id == item.Id))
    {
        // this code is executed on each item in secondList but not in firstList
    }
}

这一切正常,但它是O(n^2)。有没有办法让这更有效?我在上面链接的问题中的解决方案是使用.Except,但它不需要 lambda。

编辑: 我在上面提到了这一点,但这仍然被标记为重复。我没有两个相同对象的列表。我有两个不同对象的列表。 Type1 和 Type2 是不同的类型。他们只是都有一个我需要匹配的 id。

【问题讨论】:

  • 不是真的,因为他只是在比较 id
  • Id...不是属性吗?
  • 怎么是重复的?您标记的问题是比较两个 MyObject 列表。我没有两个相同类型的列表。我有一个 Type1 和 Type2,它们都只有一个我需要匹配的 Id。如果它在 firstList 但不在 secondList 中,如果它在 secondList 但不在 firstList 中,我需要做不同的事情。所以基本上我需要两个部分说//do something here

标签: c# list


【解决方案1】:

我建议将 2 种类型的 Id 转换为 2 个 HashSet。然后就可以了

HashSet<int> a = new HashSet<int>(firstList.Select(o => o.Id));

HashSet<int> b = new HashSet<int>(secondList.Select(o => o.Id));
if (a.IsSubsetOf(b) && b.IsSubsetOf(a))
{
    //Do your thing
}

【讨论】:

  • 用这种方法,我怎么知道是哪一种呢?如果它在集合 a 但不在集合 b 中,与如果它在集合 b 但不在集合 a 中,我需要做不同的事情。
【解决方案2】:

我不确定可用的 C#/Linq 方法。从算法的角度来看,您可以对两个列表进行排序(通常是O(n*log(n)))。然后你只需要扫描列表(线性,又名O(m+n),其中m 是列表1 中的元素数,n 是列表2 中的元素数)。假设列表 1 是较长的列表,则总复杂度为 O(m*log(m))。 不过,根据 C# HashSet 实现,Murdock 的答案可能会更快。

【讨论】:

    【解决方案3】:

    Except-方法有一个重载,它将IEqualityComparer&lt;T&gt; 作为最后一个参数。

    MSDN中有一个示例:https://msdn.microsoft.com/en-us/library/bb336390.aspx

    编辑
    可以创建匿名对象列表并将它们与特殊的IEqualityComparer&lt;T&gt; 进行比较。这是比较器类:

    class MyEqualityComparer : IEqualityComparer<object>
    {
        #region IEqualityComparer<object> Members
    
        bool IEqualityComparer<object>.Equals(object x, object y)
        {
            return (x as dynamic).Id == (y as dynamic).Id;
        }
    
        int IEqualityComparer<object>.GetHashCode(object obj)
        {
            return ((obj as dynamic).Id as object).GetHashCode();
        }
    
        #endregion
    }
    

    LINQ 表达式应该如下所示:

    var result = lst1.Select(x => new { Id = x.Id, Obj = x })
        .Except(lst2.Select(x => new { Id = x.Id, Obj = x }),
                new MyEqualityComparer())
        .Select(x => (x as dynamic).Obj as Type1);
    

    我知道,在这种情况下使用动态是一种不好的样式,您可以毫无问题地将其更改为真实类型。

    【讨论】:

    • 据我所知,IEqualityComparer 采用一种类型来相互比较。我需要对两种不同的类型进行此操作,只是它们都具有需要匹配的 Id 属性。
    猜你喜欢
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    相关资源
    最近更新 更多