如何通过使用linq C#比较两个列表来获取更新的记录

时间:2018-08-16 07:51:06

标签: c# linq

我有2个csv文件,一个是前一天,一个是当日csv文件,从前一天的csv文件中,我正在现存交易列表中收集数据,而从当天的csv文件中,我正在中处理DealList中的数据,

之后,我要检查是否根据当前csv文件与前一天的文件中的ID修改或更新了任何行。

例如 当天文件:

Id: 10 姓名:Bofa 说明:美国

前一天文件:

Id: 10 姓名:Bofa 说明:印度

如上所示,两个文件的ID = 10是相同的,但列Description值已更改,因此结果将如下所示

Id: 10 姓名:Bofa 说明:美国

如果与前一天的文件相比,当前文件中没有修改任何结果,则该结果将为null或为空。

代码:

 class Program
    {
        static void Main(string[] args)
        {

            List<Deal> dealList = new List<Deal>
            {
                new Deal{ Id = 10, Name = "Bank of America", Description = "Pay Bill"}
            };


            List<ExistingDeal> listExistingDeal = new List<ExistingDeal>
            {
                new ExistingDeal { Id = 10, Name = "Bank of America", Description = "Pay Bill"},
                new ExistingDeal { Id = 11, Name = "Bank of America11", Description = "Pay Bill"},
                new ExistingDeal { Id = 12, Name = "Bank of America12", Description = "Pay Bill"},
                new ExistingDeal { Id = 13, Name = "Bank of America13", Description = "Pay Bill"},
                new ExistingDeal { Id = 14, Name = "Bank of America14", Description = "Pay Bill"}
            };

// this is for getting new records by comparing previous day file with current day file 
            var newRecords = (from drNew in dealList
                              join drOld in listExistingDeal on drNew.Id equals drOld.Id into match
                              where !match.Any()
                              select drNew).ToList();

下面的代码用于通过比较前一天的文件从当前文件中获取更新或修改的记录-但下面的代码返回修改或更新的行,但是如果当前文件中没有任何修改或更新,则仍返回行不正确

            var updateRecords = (from drNew in dealList.AsEnumerable()
                                 join drOld in listExistingDeal on drNew.Id.ToString() equals drOld.Id.ToString()
                                 where !Equals(drNew, drOld)
                                 select drNew).ToList();

            //Below code works fin when i use data table 
            //var updateRecords = (from drNew in dt1.AsEnumerable()
            //                     join drOld in dt2.AsEnumerable() on drNew.Field<string>("Id") equals drOld.Field<string>("id")
            //                     where !DataRowComparer.Default.Equals(drNew, drOld)
            //                     select drNew).ToList();
        }

    }

    public class Deal
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    }

    public class ExistingDeal
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    }
}

谢谢。

1 个答案:

答案 0 :(得分:0)

在编写代码时需要考虑的几件事。首先,为什么要有两个具有相同数据结构的类?如果Deal和ExistingDeal在结构上相同,则没有必要。如果ExistingDeal是从Deal继承的,那么您想构建class ExistingDeal: Deal {...}之类的类。

要直接回答您的问题,我将使用Linq。有一些非常有用的linq扩展库可以为您完成此操作。不过,这是一个例子。

请注意,我在class Deal中创建了一个称为HashValues的方法。 HashValues()NameDescription中创建确定性GUID(您也可以传递更多键值)。使用类似的技术来选择性地比较类的属性,而不必遍历每个属性。

    [Test]
    public void test_compare_twolistsforchanges()
    {

        List<Deal> newDeals = new List<Deal>()
        {
            new Deal { Id = 10, Name = "Bank of America Deal Has Changed", Description = "Pay Bill"},
            new Deal { Id = 11, Name = "Bank of America11", Description = "Pay Bill"},
            new Deal { Id = 12, Name = "Bank of America12-12", Description = "Pay Bill"},
        };
        List<Deal> oldDeals = new List<Deal>
        {
            new Deal { Id = 10, Name = "Bank of America", Description = "Pay Bill"},
            new Deal { Id = 11, Name = "Bank of America11", Description = "Pay Bill"},
            new Deal { Id = 12, Name = "Bank of America12", Description = "Pay Bill"},
            new Deal { Id = 13, Name = "Bank of America13", Description = "Pay Bill"},
            new Deal { Id = 14, Name = "Bank of America14", Description = "Pay Bill"}
        };

        // Using Linq - get all new deals where the new deal and the old deal share an id 
        // AND the old deal hash doesn't match the new deal hash
        var result = newDeals
           .Where(nd => 
               oldDeals.Where(od => od.Id == nd.Id)
                  .Any(od => od.HashValues() != nd.HashValues())
               );

        System.Diagnostics.Debug.WriteLine("Changed => " + result.Count());
        System.Diagnostics.Debug.WriteLine(string.Join(Environment.NewLine, result.Select(x => x.Id)));


    }
    internal class Deal
    {
        private static System.Security.Cryptography.MD5CryptoServiceProvider hashPRovider = new System.Security.Cryptography.MD5CryptoServiceProvider();
        internal Deal() { }
        internal int Id { get; set; }
        internal string Name { get; set; }
        internal string Description { get; set; }
        internal Guid HashValues()
        {

            byte[] inputBytes = Encoding.Default.GetBytes(string.Join("", this.Name, this.Description));
            byte[] hashBytes = hashPRovider.ComputeHash(inputBytes);
            Guid hashGuid = new Guid(hashBytes);
            return hashGuid;
        }

    }