C# 使用其他属性更快地从第二个列表填充列表中的数据
我一直在寻找解决方案,但我找不到,所以我提出了这个新问题 我有两个不同班级的名单 头等舱:C# 使用其他属性更快地从第二个列表填充列表中的数据,c#,.net,linq,list,foreach,C#,.net,Linq,List,Foreach,我一直在寻找解决方案,但我找不到,所以我提出了这个新问题 我有两个不同班级的名单 头等舱: public class Class1 { public int C1Property1 {get;set;} public int C1Property2 {get;set;} public int C1Property3 {get;set;} } 二等舱: public class Class2 { public int C2Property1 {get;set;}
public class Class1
{
public int C1Property1 {get;set;}
public int C1Property2 {get;set;}
public int C1Property3 {get;set;}
}
二等舱:
public class Class2
{
public int C2Property1 {get;set;}
public int C2Property2 {get;set;}
public int C2Property3 {get;set;}
}
我有两个课程列表:
List<Class1> Class1List = new List<Class1>();
List<Class2> Class2List = new List<Class2>();
这个解决方案按照我的意图工作,但非常难看,我有2个foreach循环,速度很慢(列表可以包含10000多个元素)。在示例类中,我只编写了3个属性来说明它是如何工作的,但最初每个类都有约20个属性,其中只有2个是相同的。我能更快更有效地完成这项工作吗?也许是林克?对不起,我无法显示更多的代码。我希望你能理解我的要求。
我只需要从Class2List
中获取一个属性,并且仅当列表中的一个参数相同时,才将其放置在classlist
上
在我的第二次尝试中,我使用了如下内容:
foreach (var element1 in Class1List)
{
foreach (var element2 in Class2List.Where(element2 => element2.C2Property2 == element1.C1Property2 ))
{
element2.C2Property2 = element1.C1Property2;
break;
}
}
这应该更快,但看起来仍然很难看这是一件非常有趣的事情,但我认为类似的方法可能会奏效:
Class1List.ForEach(c1 =>
c1.C1Property1 = Class2List.Where(c2 => c2.C2Property2 == c1.C1Property2)
.Select(r => r.C2Property1)
.FirstOrDefault());
下面是一个测试类:
using System;
using System.Collections.Generic;
using System.Linq;
namespace SO_Test
{
public class ObjectA
{
public int Property1 { get; set; }
public int? Property2 { get; set; }
public override string ToString()
{
return String.Format("({0}, {1})", Property1, Property2);
}
}
public class ObjectB
{
public int Property1 { get; set; }
public int? Property2 { get; set; }
public override string ToString()
{
return String.Format("({0}, {1})", Property1, Property2);
}
}
class Program
{
static void Main()
{
var listA = new List<ObjectA>
{
new ObjectA { Property1 = 5, Property2 = null },
new ObjectA { Property1 = 16, Property2 = null },
new ObjectA { Property1 = 9, Property2 = null },
new ObjectA { Property1 = 38, Property2 = null }
};
var listB = new List<ObjectB>
{
new ObjectB { Property1 = 5, Property2 = 1 },
new ObjectB { Property1 = 9, Property2 = 2 },
new ObjectB { Property1 = 16, Property2 = 3 }
};
Console.WriteLine("BEFORE");
Console.WriteLine("ListA: {0}", String.Join(", ", listA));
Console.WriteLine("ListB: {0}", String.Join(", ", listB));
listA.ForEach(a =>
a.Property2 = listB.Where(b => b.Property1 == a.Property1)
.Select(r => r.Property2)
.FirstOrDefault());
Console.WriteLine("AFTER");
Console.WriteLine("ListA: {0}", String.Join(", ", listA));
Console.WriteLine("ListB: {0}", String.Join(", ", listB));
Console.ReadLine();
}
}
}
这是一件非常有趣的事情,但我认为类似的事情可能会奏效:
Class1List.ForEach(c1 =>
c1.C1Property1 = Class2List.Where(c2 => c2.C2Property2 == c1.C1Property2)
.Select(r => r.C2Property1)
.FirstOrDefault());
下面是一个测试类:
using System;
using System.Collections.Generic;
using System.Linq;
namespace SO_Test
{
public class ObjectA
{
public int Property1 { get; set; }
public int? Property2 { get; set; }
public override string ToString()
{
return String.Format("({0}, {1})", Property1, Property2);
}
}
public class ObjectB
{
public int Property1 { get; set; }
public int? Property2 { get; set; }
public override string ToString()
{
return String.Format("({0}, {1})", Property1, Property2);
}
}
class Program
{
static void Main()
{
var listA = new List<ObjectA>
{
new ObjectA { Property1 = 5, Property2 = null },
new ObjectA { Property1 = 16, Property2 = null },
new ObjectA { Property1 = 9, Property2 = null },
new ObjectA { Property1 = 38, Property2 = null }
};
var listB = new List<ObjectB>
{
new ObjectB { Property1 = 5, Property2 = 1 },
new ObjectB { Property1 = 9, Property2 = 2 },
new ObjectB { Property1 = 16, Property2 = 3 }
};
Console.WriteLine("BEFORE");
Console.WriteLine("ListA: {0}", String.Join(", ", listA));
Console.WriteLine("ListB: {0}", String.Join(", ", listB));
listA.ForEach(a =>
a.Property2 = listB.Where(b => b.Property1 == a.Property1)
.Select(r => r.Property2)
.FirstOrDefault());
Console.WriteLine("AFTER");
Console.WriteLine("ListA: {0}", String.Join(", ", listA));
Console.WriteLine("ListB: {0}", String.Join(", ", listB));
Console.ReadLine();
}
}
}
因此,我有三个选择: 使用LINQ 我的机器用了4.58秒,每个列表中有20000个元素。虽然代码看起来(在我看来)好一点,但实际上它与您的代码是一样的 使用字典 使用字典通过散列访问
Class2
元素非常有效:
Dictionary<int, Class2> dictionary = Class2List.GroupBy(e2 => e2.C2Property2, e2 => e2).Select(elements => elements.First()).ToDictionary(e2 => e2.C2Property2, e2 => e2);
Class1List.ForEach(element1 =>
{
if (dictionary.ContainsKey(element1.C1Property2))
element1.C1Property1 = dictionary[element1.C1Property2].C2Property1;
});
Dictionary Dictionary=Class2List.GroupBy(e2=>e2.C2Property2,e2=>e2)。选择(elements=>elements.First()).ToDictionary(e2=>e2.C2Property2,e2=>e2);
ClassList.ForEach(元素1=>
{
if(dictionary.ContainsKey(element1.C1Property2))
element1.C1Property1=字典[element1.C1Property2].C2Property1;
});
这使我的机器在每个列表中花费了0.00878个元素
平行的
<>如果你的数据真的很大,你可以考虑使用< /P>
字典=
GroupBy(e2=>e2.C2Property2,e2=>e2)。选择(elements=>elements.First()).ToDictionary(e2=>e2.C2Property2,e2=>e2);
Parallel.ForEach(ClassList,element1=>
{
if(dictionary.ContainsKey(element1.C1Property2))
element1.C1Property1=字典[element1.C1Property2].C2Property1;
});
但由于每个列表中只有20000个元素,因此我的机器比非并行版本花费的时间更长(0.0197s)。因此,我有三个选项: 使用LINQ 我的机器用了4.58秒,每个列表中有20000个元素。虽然代码看起来(在我看来)好一点,但实际上它与您的代码是一样的 使用字典 使用字典通过散列访问
Class2
元素非常有效:
Dictionary<int, Class2> dictionary = Class2List.GroupBy(e2 => e2.C2Property2, e2 => e2).Select(elements => elements.First()).ToDictionary(e2 => e2.C2Property2, e2 => e2);
Class1List.ForEach(element1 =>
{
if (dictionary.ContainsKey(element1.C1Property2))
element1.C1Property1 = dictionary[element1.C1Property2].C2Property1;
});
Dictionary Dictionary=Class2List.GroupBy(e2=>e2.C2Property2,e2=>e2)。选择(elements=>elements.First()).ToDictionary(e2=>e2.C2Property2,e2=>e2);
ClassList.ForEach(元素1=>
{
if(dictionary.ContainsKey(element1.C1Property2))
element1.C1Property1=字典[element1.C1Property2].C2Property1;
});
这使我的机器在每个列表中花费了0.00878个元素
平行的
<>如果你的数据真的很大,你可以考虑使用< /P>
字典=
GroupBy(e2=>e2.C2Property2,e2=>e2)。选择(elements=>elements.First()).ToDictionary(e2=>e2.C2Property2,e2=>e2);
Parallel.ForEach(ClassList,element1=>
{
if(dictionary.ContainsKey(element1.C1Property2))
element1.C1Property1=字典[element1.C1Property2].C2Property1;
});
但由于每个列表中只有20000个元素,我的机器比非并行版本花费的时间更长(0.0197s)。我编辑了你的文章,因此更容易阅读。至于你的问题,我不知道如何使它更有效率。即使您确实使用Linq使其成为一个单行程序,如果我没有弄错的话,它仍然会在幕后执行foreach循环。但是这里有很多人的知识比我多,所以也许其他人有一个可行的建议@NSNoob该问题将两个不同类的列表合并为一个,而OP希望将list1中一个对象值的属性设置为list2中的另一个对象值(并比较其他两个属性是否相等)。@KevinCruijssen oh Ok。谢谢你解释kevinYea对英语很抱歉,我知道这很难理解:)你为什么不在设置好酒店后休息一下呢?Class2List中是否有可能(并且想要)有更多的元素具有相同的属性并且应该更改element1的属性?这不是1的最快解决方案。对两个列表进行排序,2。使用带有
index1
和index2
的单个while
,其中只增加索引,从而松开list1.PropertyA.CompareTo(list2.Property2)
。应该给你更少的迭代次数。特别是如果列表相似的话。我已经编辑了你的帖子,这样更容易阅读。至于你的问题,我不知道如何使它更有效率。即使您确实使用Linq使其成为一个单行程序,如果我没有弄错的话,它仍然会在幕后执行foreach循环。但是这里有很多人的知识比我多,所以也许其他人有一个可行的建议@NSNoob该问题将两个不同类的列表合并为一个,而OP希望将list1中一个对象值的属性设置为list2中的另一个对象值(并比较其他两个属性是否相等)。@KevinCruijssen oh Ok。谢谢你解释kevinYea对英语很抱歉,我知道这很难理解:)你为什么不在设置好酒店后休息一下呢?Class2List中是否可能(并且需要)有更多的元素具有相同的属性并且应该更改element1的属性?这不是最快的解决方案吗
Dictionary<int, Class2> dictionary =
Class2List.GroupBy(e2 => e2.C2Property2, e2 => e2).Select(elements => elements.First()).ToDictionary(e2 => e2.C2Property2, e2 => e2);
Parallel.ForEach(Class1List, element1 =>
{
if (dictionary.ContainsKey(element1.C1Property2))
element1.C1Property1 = dictionary[element1.C1Property2].C2Property1;
});