简体   繁体   English

比较3个列表与不同类型数据的最佳方法

[英]Best way to compare 3 lists with different types of data

I'm trying to find the best way to compare 3 lists in C# and then merge the result into one csv file. 我试图找到最好的方法来比较C#中的3个列表,然后将结果合并到一个csv文件中。 My code takes quite a lot of time to process my data and i want to improve this. 我的代码需要花费大量时间来处理我的数据,我想对此进行改进。

What I do at the moment is comparing 2 lists at a time using LINQ, saving the result for each comparison into a temporary list and then merge it before saving it as a csv file. 目前,我要做的是使用LINQ一次比较两个列表,将每个比较的结果保存到一个临时列表中,然后合并它,然后再将其保存为csv文件。

An example of one of my list compares: 我的列表之一的示例进行了比较:

foreach (RemedyAsset remedyAsset in RemedyAssetsList)
        {
            MIAsset tempMIAsset = null;

            tempMIAsset = MIAssetsList.FirstOrDefault(m => m.CIName.ToUpper() == remedyAsset.CIName.ToUpper());

            if (tempMIAsset == null)
            {
                TempAssets.Add(new TempAsset
                {
                    Asset = remedyAsset.CIName,
                    LastMiActivity = string.Empty,
                    RemedyStatus = remedyAsset.Status,
                    InMI = false,
                    InRemedy = true
                });
            }
            else
            {
                TempAssets.Add(new TempAsset
                {
                    Asset = remedyAsset.CIName,
                    LastMiActivity = tempMIAsset.LastActiveTime,
                    RemedyStatus = remedyAsset.Status,
                    InMI = true,
                    InRemedy = true
                });
            }
        }

My lists originates from 3 different IT systems(BMC Remedy, Active Directory, Checkpoint), which has one common variable: An asset number. 我的列表来自3个不同的IT系统(BMC Remedy,Active Directory,Checkpoint),它们具有一个公共变量:资产编号。

My lists look like this: 我的列表如下所示:

-(List1)RemedyReport: Asset number - Remedy status. -(List1)RemedyReport:资产编号-补救状态。
-(List2)ADReport: Asset number - last logon time - last password change. -(List2)ADReport:资产编号-上次登录时间-上次密码更改。
-(List3)MIReport: Asset number - last server contact. -(List3)MIReport:资产编号-上次服务器联系。

When I compare the lists, I also check if an asset number isn't present in a list and this also needs to be shown in the output csv file. 比较列表时,我还会检查列表中是否不存在资产编号,这也需要在输出的csv文件中显示。 I then needs to merge data from the lists where a matching asset number is present and the output will look like this: 然后,我需要合并存在匹配资产编号的列表中的数据,并且输出将如下所示:
Asset number - In Remedy - In MI - In AD - Last server contact - Last Logon - Last password change 资产编号-解决方法-MI中-AD中-上次服务器联系-上次登录-上次密码更改

What is the best way to compare 3 lists? 比较3个列表的最佳方法是什么?
Is there any best practices when doing a compare of 3 or more lists? 比较3个或更多列表是否有最佳实践?

This is my first post in here, please let me know if I've done anything wrong. 这是我在这里的第一篇文章,如果做错任何事情,请告诉我。

Solution based on Samar's suggestion 基于Samar的建议的解决方案
My adaption of Samar's suggestion, which fulfilled my needs. 我对Samar的建议进行了调整,从而满足了我的需求。 Performance improvement from 9 minutes to just under 2 minutes. 性能从9分钟提高到不到2分钟。

public void compare()
        {
            //Creating dummy data for testing
            List<C1> L1 = new List<C1>() { new C1() { ID = 1, classC1="test1" }, new C1() { ID = 4, classC1="test1" } };
            List<C2> L2 = new List<C2>() { new C2() { ID = 1, classC2="test2" }, new C2() { ID = 2, classC2="test2" } };
            List<C3> L3 = new List<C3>() { new C3() { ID = 1 }, new C3() { ID = 2, classC3="test3" }, new C3() { ID = 3, classC3="test3" } };

            //Creating new list which will contain all the objects without duplicates based on ID column
            List<C4> L4 = new List<C4>();

            //Firstly add all the objects from L1
            L4.AddRange(from l1 in L1 select new C4() { ID = l1.ID, classC1=l1.classC1 });

            //Add only those objects from L3 which are not part of L1
            L4.AddRange(from l22 in L2
                        where !(L4.Where(l44 => l44.ID == l22.ID)
                                .Select(l44 => { l44.classC2 = l22.classC2; return l44; }).Any(p => p.ID == l22.ID))
                        select new C4() { ID = l22.ID, classC2 = l22.classC2 });

            //Add only those objects from L3 which are not part of L1 and L2
            L4.AddRange(from l33 in L3
                        where !(L4.Where(l44 => l44.ID == l33.ID)
                                .Select(l44 => { l44.classC3 = l33.classC3; return l44; }).Any(p => p.ID == l33.ID))
                        select new C4() { ID = l33.ID, classC3 = l33.classC3 });

            //L4 will now contain all IDs without duplicates
        }

        class C1
        {
            public int ID { get; set; }
            public string classC1 { get; set; }

            //will contain other properties
        }

        class C2
        {
            public int ID { get; set; }
            public string classC2 { get; set; }

            //will contain other properties
        }

        class C3
        {
            public int ID { get; set; }
            public string classC3 { get; set; }

            //will contain other properties
        }

        class C4
        {
            public int ID { get; set; }
            public string classC1 { get; set; }
            public string classC2 { get; set; }
            public string classC3 { get; set; }

            //will contain other properties or maybe a combination of all the properties of C1, C2 and C3
        }

I am not able to understand your class structure so I will try to answer your question in a more generic manner. 我无法理解您的课程结构,因此我将尝试以更通用的方式回答您的问题。

Firstly let me understand what you exactly need. 首先,让我了解您的确切需求。

Say you have 3 lists with 3 different classes in them. 假设您有3个清单,其中有3个不同的类别。 So you have lists L1, L2 and L3 and within them are classes C1, C2 and C3 respectively. 因此,您具有列表L1,L2和L3,其中分别是类C1,C2和C3。

You need a single list say L4 with another (or one of the above?) class say C4 and this list should not contain duplicates based on some common property in all the 3 classes. 您需要一个列表,说L4以及另一个(或上面的一个?)类,说C4,并且此列表不应包含基于所有3类中某些共同属性的重复项。

My take to this problem is the following code. 我对这个问题的理解是下面的代码。 I am not very sure if this is efficient but it sure works. 我不太确定这是否有效,但确实有效。 It is also not generic ie applicable to any number of list with any set of classes implementing a certain interface. 它也不是通用的,即适用于具有实现某个接口的任何类集的任何数量的列表。 Try it out and let me know if, performance wise, it is creating a problem or in any other way for that matter. 尝试一下,让我知道在性能方面是否正在造成问题或以其他任何方式解决此问题。

I hope this helps. 我希望这有帮助。

Regards, 问候,

Samar 萨马尔

    private void btnCompare_Click(object sender, EventArgs e)
    {
        //Creating dummy data for testing
        List<C1> L1 = new List<C1>() { new C1() { ID = 1 }, new C1() { ID = 4 } };
        List<C2> L2 = new List<C2>() { new C2() { ID = 1 }, new C2() { ID = 2 } };
        List<C3> L3 = new List<C3>() { new C3() { ID = 1 }, new C3() { ID = 2 }, new C3() { ID = 3 } };

        //Creating new list which will contain all the objects without duplicates based on ID column
        List<C4> L4 = new List<C4>();

        //Firstly add all the objects from L1
        L4.AddRange(from l1 in L1 select new C4() { ID = l1.ID });

        //Add only those objects from L2 which are not part of L1
        L4.AddRange(from l22 in L2
                    where !(from l4 in L4 join l2 in L2 on l4.ID equals l2.ID select new { ID = l4.ID }).Any(p => p.ID == l22.ID) 
                    select new C4() { ID = l22.ID });

        //Add only those objects from L3 which are not part of L1 and L2
        L4.AddRange(from l33 in L3
                    where !(from l4 in L4 join l3 in L3 on l4.ID equals l3.ID select new { ID = l4.ID }).Any(p => p.ID == l33.ID)
                    select new C4() { ID = l33.ID });

        //L4 will now contain all IDs without duplicates
    }

    class C1
    {
        public int ID { get; set; }

        //will contain other properties
    }

    class C2
    {
        public int ID { get; set; }

        //will contain other properties
    }

    class C3
    {
        public int ID { get; set; }

        //will contain other properties
    }

    class C4
    {
        public int ID { get; set; }

        //will contain other properties or maybe a combination of all the properties of C1, C2 and C3
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM