按第一个列表的键合并两个列表

时间:2011-02-14 03:22:40

标签: c# .net hashcode

我的主要问题描述如下:

我有两个BankAccount个对象列表。 BankAccount具有唯一标识帐户的BankCodeAccountNumber等属性。因此,这两个列表可能包含相同的银行帐户,但他们的SourceAmountAccountTypes可能会有所不同。

这里的目的是合并这两个列表:

  1. 如果帐户在第二个列表中可用(但不在第一个列表中),则将帐户添加到第一个列表中。
  2. 如果两个列表中的银行帐户相同,请使用第二个列表中(匹配的)银行帐户的详细信息更新第一个列表中银行帐户的详细信息。
  3. 我已尝试实施一个SO post中提到的解决方案。我去尝试在.NET代码填充网站上编写代码。但是在尝试执行行号后,我无法获得输出。 93我评论过。

    class BankAccount
    {
        public string BankCode{get;set;}
        public string AccountNumber{get;set;}
        public string AccountType{get;set;}
        public string Amount{get;set;}
        public string Source{get;set;}
    
        public override bool Equals(object obj)
        {
          var acc = obj as BankAccount;
          return Equals(acc);
        }
    
        public override int GetHashCode()
        {
          return this.GetHashCode();
        }
    
        public bool Equals(BankAccount acc2)
        {
          if(acc2 == null) return false;
          if(string.IsNullOrEmpty(acc2.BankCode)) return false;
          if(string.IsNullOrEmpty(acc2.AccountNumber)) return false;
          return this.BankCode.Equals(acc2.BankCode) && this.AccountNumber.Equals(acc2.AccountNumber);
        }
    }
    
    //List<BankAccount> lst3 = lst.Union(lst1).ToList();  // line 93
    

    可以查看完整代码here

    PS:我不确定这是否会成为键盘网站的问题。

    更新 - 2011年2月14日星期一 - 格林尼治标准时间4:50:24(am)/ 04:50:24

    Thanx进行更新。但有些事情仍然存在问题。在输出中,列表3的第一个项目应为AccountType=PSource=lst2。第二个要求未得到满足。我认为Union()只是我需要的一部分。我需要做什么来满足第二个要求。

    drachenstern的

    编辑:我不确定这个标题是否更好,但对于实际问题,它肯定比之前的标题更具信息性:\

2 个答案:

答案 0 :(得分:5)

解决方案1:

此解决方案未达到您(新)规定的2个要求,但旨在解决您尝试使用LINQ Union()解决问题的问题。

你有一个递归调用,导致这一行的堆栈溢出异常(23):

public override int GetHashCode()
{
    return this.GetHashCode();
}

我建议将其更改为:

public override int GetHashCode()
{
    return (BankCode + AccountNumber).GetHashCode();
}

修改

确保成员BankCount和AccountNumber永远不会为null或抛出异常。我建议你查找覆盖GetHashCode()方法的标准做法。

Resharper 自动生成的GetHashCode覆盖: (397值确保在交换BankCode和AccountNumber时数字不会发生冲突。未选中表示数字不会出现溢出问题* 397)

public override int GetHashCode()
{
    unchecked
    {
        return ((BankCode != null ? BankCode.GetHashCode() : 0)*397) ^ (AccountNumber != null ? AccountNumber.GetHashCode() : 0);
    }
}

解决方案2:

此解决方案旨在实现您的2个要求,而无需使用LINQ Union()。

如果您想要合并列表,请使用第二个列表作为首选项,然后尝试:

var mergedList = new List<BankAccount>();
// add items from lst or any duplicates from lst1
foreach (var bankAccount in lst)
{
    var account = bankAccount;
    var dupe = lst1.FirstOrDefault(item => item.Equals(account));
    mergedList.Add(dupe ?? bankAccount);
}
// add any items in lst1 that are not duplicates
foreach (var bankAccount in lst1.Where(item=>!mergedList.Contains(item)))
{
    mergedList.Add(bankAccount);
}

如果您正在寻找代码最小化:

// add items from lst or any duplicates from lst1
var temp = lst.Select(item => lst1.FirstOrDefault(item1 => item1.Equals(item)) ?? item);
// add any items in lst1 that are not duplicates
var result = temp.Union(lst1.Where(item => !temp.Contains(item)));

答案 1 :(得分:0)

问题是BankAccount类中的这个方法。它导致堆栈溢出,因为它一直在调用自己。

public override int GetHashCode()
{
  return this.GetHashCode();
}

尝试使用this.ToString()。GetHashCode()并使用对类有意义的东西覆盖ToString。