假设我们有这些业务对象具有一些共同的属性:
public class A
{
// Properties in common
public int Common { get; set; }
public string aValue { get; set; }
// Some other goes here.
}
public class B
{
// Properties in common
public int Common { get; set; }
public string bValue { get; set; }
// Some other goes here.
}
在我们的业务逻辑中,我们有两个像这样的列表:
List<A> aList = new List<A>();
List<B> bList = new List<B>();
(假设我们这些列表中至少填充了100个实例) 好吧,让我们从我们的问题开始,我们需要迭代aList,以便在bList中设置每个实例的一个属性,当然这个属性与共同的属性匹配,如下所示:
foreach (A a in aList)
{
B b = bList.Find(x => x.Common == a.Common);
if (b != null)
b.bValue = a.aValue;
}
有没有人知道改善此操作的更好方法,因为它导致我们的应用程序需要花费太多时间才能完成?
感谢,
答案 0 :(得分:4)
由于列表中的Find
是线性的,因此效果不佳。生成的算法为O(n^2)
。
您应该使用公共属性上的Dictionary
制作bList
,然后按键查找,而不是使用Find
进行搜索;字典查找是O(1)
分摊的,因此它会使您的算法在列表长度上呈线性。
var dict = bList.ToDictionary(b => b.Common);
foreach (A a in aList) {
B b;
if (dict.TryGetValue(a.Common, out b) {
b.bValue = a.aValue;
}
}
答案 1 :(得分:2)
为了有效地查找值,给定某个键,您不会使用列表,而是使用字典。要查找列表中的特定项,需要O(N),在字典中需要O(1)。
Dictionary<int, B> bDict = new Dictionary<int, B>();
foreach (B b in bList) bDict.Add(b.Common, b);
foreach (A a in aList) {
if (bDict.ContainsKey(a.Common))
bDict[a.Common].bValue = a.aValue;
}
答案 2 :(得分:1)
将bList复制到以Common作为键的字典类型容器中,并在循环中使用它而不是bList本身。
答案 3 :(得分:1)
我相信如果您在linq中进行连接,它将在两个列表上为您执行散列连接,这将节省您手动创建字典,如其他答案中所建议的那样。我没有在这台机器上安装工作室来鞭打你的样品,稍后会尝试更新。
如果项目数量非常小,Linq甚至可能足够聪明,不会启动哈希联接。
编辑: 给这样的东西一个旋转:
var joined = from a in aList
join b in bList on a.Common equals b.Common
select new {
A = a,
B = b
};
foreach (var item in joined)
{
item.B.bValue = item.A.aValue;
}