【问题标题】:Find and select specific changes between two object lists查找并选择两个对象列表之间的特定更改
【发布时间】:2014-04-10 18:59:08
【问题描述】:

我有两个对象 T 列表。每个 T 都有唯一的键“T.key”

List<T> List1;
List<T> List2;

我想创建一个所有对象的键列表,这些对象仅在 List2 中,但也包含在两个列表中但具有特定属性差异的对象(我们将它们命名为 T.a 和 T.b)。列表内容也不一定是相同的顺序。

输入/输出示例:

List1 = {{key:1,a:10,b:10,c:10}, {key:2,a:10,b:10,c:10}, {key:3,a:10,b:10,c:10}}
List2 = {{key:1,a:10,b:10,c:99}, {key:2,a:11,b:10,c:10}, {key:4,a:10,b:10,c:10}}

Result = {2,4}

【问题讨论】:

  • 前半段很直接,后半段你的问题没有多大意义
  • “不在两个列表中”是不是意味着“只在一个列表中”?
  • 我把“不在两个列表中”的意思是“不在L2”。
  • 是的,我认为两个输入列表的一些示例数据以及您对输出的期望将极大地阐明需要什么
  • OK,你的编辑很清楚。

标签: c# list object properties compare


【解决方案1】:

生成预期键的完整示例:2 和 4

List<F> L1 = new List<F>{new F(1,10,10,10), new F(2,10,10,10), new F(3,10,10,10)};
List<F> L2 = new List<F>{new F(1,10,10,99), new F(2,11,10,10), new F(4,10,10,10)}; 

void Main() { // Client code. One call covers the biz logic (and sample output)
    // Must call Except on L2 with L1 as the arg for proper eval of biz logic
    foreach ( var item in L2.Except(L1, new CompareListsOfObjsF()) ) 
        Console.WriteLine("key: " + item.key);  
}

class F { // Quick, dirty sample POCO w/ constructor
    public int key, a, b, c; 
    public F(int mk, int ma, int mb, int mc) { key=mk; a=ma; b=mb; c=mc; }
} 

class CompareListsOfObjsF : IEqualityComparer<F> {
    // business-specific equality logic - notice that 'c' is not evaluated
    public bool Equals(F x, F y) {
        return  x.key == y.key && x.a == y.a && x.b == y.b;
    }
    // The logic will not work without a proper hash function:
    public int GetHashCode(F x) { unchecked { // Overflow is ok
            int h = 17 * 23 + x.key;
            h += h * 23 + x.a;
            h += h * 23 + x.b;
            return h; // c has to be left out for selection biz logic to work
      }
   } 
}

输出:

键:2

键:4

【讨论】:

  • 很好......你打败了我......我认为这是更新问题的最佳答案。您可能会补充说,他还可以将IEqualityComparer 构建到他的F 类中。 GetHashCode 也应该返回键的哈希码,a 和 b xor'd 一起或类似的东西。
  • @Kevin:感谢您的赞誉。我重新组织了样本并添加了一些 cmets。 HashCode 是一个完整的 hack,旨在满足编译器的要求。它的实施对 OP 没有影响。如果 OP 需要一个运行良好的哈希码,那么这是一个单独的问题。 :-) 但我确实同意,鉴于业务规则,POCO 应该包含 IEqualityComparer 的实现。无论如何,这些碎片都在那里,干净地分开,供 OP 随意使用。
  • 是的,我知道不想费力地通过哈希码函数......有一件事......我要添加一个注释,如果你打算将它们放在字典/哈希表中,IEquality 比较器应该实现 GetHashCode / 等你需要哈希码的地方。
  • @Kevin:哎呀......我在玩散列,并注意到我从 Jon Skeet 的一个著名答案中提取的散列函数产生了不正确的结果。一开始我很困惑,但后来意识到,Except 函数在其实现中必须使用 Dictionary/HashSet。所以,吸取教训。总是到一个适当的 impl。的GetHashCode。返回值 1 的技巧恰好奏效了!
  • 非常好。我会投赞成票,但我已经投了。既然你提到了它,我意识到我之前遇到过这个问题,但已经有一段时间了。这就是为什么你必须给它一个IEqualityComparer,因为它需要GetHashCode()
【解决方案2】:

这会产生您预期的输出:

 List<T> list1 = new List<T> { new T { key = 1, a = 10, b = 10, c = 10 }, new T { key = 2, a = 10, b = 10, c = 10 }, new T { key = 3, a = 10, b = 10, c = 10 } };
 List<T> list2 = new List<T> { new T { key = 1, a = 10, b = 10, c = 99 }, new T { key = 2, a = 11, b = 10, c = 10 }, new T { key = 4, a = 10, b = 10, c = 10 } };

 List<int> difference = new List<int>();

 foreach (var item2 in list2)
 {
     var item1 = list1.FirstOrDefault(i => i.key == item2.key);

     if (item1 != null)
     {
         if (item2.a == item1.a && item2.b == item1.b)
             continue;
     }           

     difference.Add(item2.key);
 }

difference 包含{2,4}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 2013-05-02
    • 2016-05-27
    • 2023-03-28
    相关资源
    最近更新 更多