在第3个列表.net 4.0中比较2个列表和返回差异

时间:2015-11-17 08:38:43

标签: c# linq

我正在尝试比较2个列表并输出另一个列表中的差异。比较每个属性值基于CustomerNo.I知道这已被多次询问但我似乎无法找到究竟是什么 我正在寻找,所以请不要急于说它是重复的。

我的问题是

1)如何转换为哈希集以提高性能(尝试转换为hashset但不返回与列表相同的结果。

2)如何返回“差异”列表。区别我的意思是,如果1个列表中的customerNo具有多个属性,这些属性应该添加到列表中

任何建议

这就是我所做的

    class Program
        {
            static void Main()
            {
                Customer[] oldCustomersSet =
                {
                    new Customer { CustomerNo="1", Name = "Joe", Surname = "Bloggs", City = "London"},
                    new Customer {CustomerNo="2",Name = "Mark", Surname = "Smith", City = "Manchester"},
                    new Customer {CustomerNo="3",Name = "Emily", Surname = "Blunt", City = "Liverpool"},
                    new Customer {CustomerNo="4",Name = "George", Surname = "William", City = "Exter"},
                    new Customer {CustomerNo="5",Name = "aaa", Surname = "bbb", City = "Exter"},
                    new Customer {CustomerNo="6",Name = "ccc", Surname = "ddd", City = "Exter"},
                    new Customer {CustomerNo="7",Name = "Jane", Surname = "Wonder", City = "Exter"},
                };
                Customer[] newCustomersSet =
                {
                    new Customer {CustomerNo="1",Name = "Joe", Surname = "Bloggs", City = "London"},
                    new Customer {CustomerNo="2",Name = "Mark", Surname = "WrongSurname", City = "Manchester"},
                    new Customer {CustomerNo="3",Name = "Emily", Surname = "Blunt", City = "Liverpool"},
                    new Customer {CustomerNo="4",Name = "George", Surname = "William", City = "WrongCity"},
                    new Customer {CustomerNo="5",Name = "aaa", Surname = "bbb", City = "Exter"},
                    new Customer {CustomerNo="6",Name = "ccc", Surname = "ddd", City = "Exter"},
                    new Customer {CustomerNo="7",Name = "Jane", Surname = "Wonder", City = "ExterMistake"},
                };

                 var firstSet = oldCustomersSet.Except(newCustomersSet);
        var secondSet = newCustomersSet.Except(oldCustomersSet);

                //This returns 6 items (3 old and 3 new)
                var result = firstSet.Union(secondSet).ToList();

                //now find all the differences.How do I match it based on customerNo and write to the difference List?
                List<Difference>diffList=new List<Difference>();

            }
        }

    }

    public class Difference
    {
        public string PropertyName { get; set; }
        public string OldValue { get; set; }
        public string NewValue { get; set; }
    }
    public class Customer : IEquatable<Customer>
    {

        public string CustomerNo { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
        public string City { get; set; }

        public bool Equals(Customer other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return string.Equals(City, other.City)
                && string.Equals(CustomerNo, other.CustomerNo)
                && string.Equals(Name, other.Name)
                && string.Equals(Surname, other.Surname);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != this.GetType()) return false;
            return Equals((Customer)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                var hashCode = (City != null ? City.GetHashCode() : 0);
                hashCode = (hashCode * 397) ^ (CustomerNo != null ? CustomerNo.GetHashCode() : 0);
                hashCode = (hashCode * 397) ^ (Name != null ? Name.GetHashCode() : 0);
                hashCode = (hashCode * 397) ^ (Surname != null ? Surname.GetHashCode() : 0);
                return hashCode;
            }
        }

        public static bool operator ==(Customer left, Customer right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(Customer left, Customer right)
        {
            return !Equals(left, right);
        }

1 个答案:

答案 0 :(得分:1)

您必须加入这两个数组,以便使用Join扩展方法。

要实际生成“差异”列表,请创建一个比较匹配的新老客户的属性的方法。

这是一个快速而肮脏的例子:

public IEnumerable<Difference> GetDifferences(Customer oldOne, Customer newOne)
{
    var props = typeof(Customer).GetProperties();

    foreach (var prop in props)
    {
        var oldvalue = prop.GetValue(oldOne);
        var newvalue = prop.GetValue(newOne);
        if(oldvalue != newvalue)
            yield return new Difference { CustomerNo = oldOne.CustomerNo, PropertyName = prop.Name, OldValue = oldvalue.ToString(), NewValue = newvalue.ToString() };
    }
}

像这样使用(根据需要调整):

var result = oldCustomersSet.Join(newCustomersSet, 
                                  o => o.CustomerNo, 
                                  i => i.CustomerNo,
                                  GetDifferences)
                            .Where(d => d.Any())
                            .ToLookup(d => d.First().CustomerNo);

产生这个结果:

enter image description here

(注意我向CustomerNo添加了Difference属性

如果您的两个列表/数组都已排序,并且第一个列表中某个索引处的每个元素对应于第二个列表中同一索引处的同一个客户,那么您也可以使用简单的for循环。

var diffs = new List<Tuple<string, List<Difference>>>();
for(int i = 0; i < oldCustomersSet.Length; i++)
{
    var curDiffs = GetDifferences(oldCustomersSet[i], newCustomersSet[i]).ToList();
    if(curDiffs.Any())
        diffs.Add(Tuple.Create(oldCustomersSet[i].CustomerNo, curDiffs));
}

但要知道这是否真的更快,你必须实际测试它。