我试图找到比较C#中3个列表的最佳方法,然后将结果合并到一个csv文件中。我的代码需要花费大量时间来处理我的数据,我想改进它。
我目前所做的是使用LINQ一次比较2个列表,将每个比较的结果保存到临时列表中,然后在将其保存为csv文件之前将其合并。
我的一个列表的示例比较:
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
});
}
}
我的列表来自3个不同的IT系统(BMC Remedy,Active Directory,Checkpoint),它有一个共同的变量:资产编号。
我的列表如下所示:
- (List1)RemedyReport:资产编号 - 补救状态。
- (List2)ADReport:资产编号 - 上次登录时间 - 上次密码更改。
- (List3)MIReport:资产编号 - 最后一次服务器联系。
当我比较列表时,我还检查列表中是否存在资产编号,这也需要在输出csv文件中显示。
然后,我需要合并存在匹配资产编号的列表中的数据,输出将如下所示:
资产编号 - 补救措施 - 在MI中 - 在AD中 - 上次服务器联系 - 上次登录 - 上次密码更改
比较3个列表的最佳方法是什么? 在比较3个或更多列表时是否有最佳实践?
这是我在这里的第一篇文章,如果我做错了,请告诉我。
基于Samar建议的解决方案
我改编了Samar的建议,满足了我的需求。
性能从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
}
答案 0 :(得分:0)
我无法理解您的班级结构,所以我会尝试以更通用的方式回答您的问题。
首先让我了解你的确需要。
假设您有3个列表,其中包含3个不同的类。所以你有列表L1,L2和L3,其中分别是C1,C2和C3类。
你需要一个单独的列表说L4与另一个(或上面的一个?)类说C4并且这个列表不应该包含基于所有3个类中的一些共同属性的重复。
我对此问题的看法是以下代码。我不太确定这是否有效,但确实有效。它也不是通用的,即适用于具有实现特定接口的任何类集合的任何数量的列表。尝试一下,让我知道,从表现的角度来看,它是在创造问题还是以任何其他方式解决问题。
我希望这会有所帮助。
此致
萨马
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
}