3

假设我们有这些具有一些共同属性的业务对象:

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;
}

有谁知道改进此操作的更好方法,因为它导致我们的应用程序需要太多时间才能完成?

谢谢,

4

4 回答 4

4

这表现不佳,因为Find列表是线性的。得到的算法是O(n^2)

您应该DictionarybListcommon 属性上创建一个,并通过 key 查找而不是使用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;
    }
}
于 2012-04-18T00:39:44.750 回答
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;
}
于 2012-04-18T00:42:02.270 回答
1

将您的 bList 复制到以 Common 作为键的字典类型容器中,并在循环中使用它而不是 bList 本身。

于 2012-04-18T00:38:35.663 回答
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;
            }
于 2012-04-18T00:47:53.473 回答