在C#中比较和更新两个列表

时间:2011-05-03 13:24:38

标签: c# linq list

上下文是我在内存中有一组高速缓存的值,这些值很难获取,而另一组相关数据的获取成本低廉且无法缓存(业务规则)。我已经完成了所有工作,但我只是想知道是否有人能想到一种更便宜的方式进行这种更新......

    foreach (var nonCachedItem in searchItemsNonCached)
    {
        foreach (var cachedItem in searchItemsCached)
        {
            if (cachedItem.ID == nonCachedItem.ID)
                nonCachedItem.Description = cachedItem.Description;
        }
    }

它基本上只是将缓存的信息与我刚收到的信息相匹配。这一切都有效,负载几乎可以忽略不计,但我对提高效率很有帮助。

编辑:在上面,searchItemsNonCached和searchItemsCached都是SearchItem的列表,其中Searchitem是一个定制的对象。

4 个答案:

答案 0 :(得分:5)

将缓存的项目存储在字典中。现在只有在密钥存在时才能更新。

答案 1 :(得分:2)

使用缓存的项加载Dictionary,然后循环浏览每个非缓存项,以查找字典中的匹配项。这是O(n),而不是嵌套循环O(n^2)

var cachedDictionary = new Dictionary<int, YourType>();
foreach (var item in searchItemsCached)
{
  cachedDictionary.Add(item.ID, item);
}
foreach (var item in searchItemsNonCached)
{
  YourType match;
  if (cachedDictionary.TryGetValue(out match))
  {
    item.Description = match.Description;
  }
}

如果您可以考虑从一开始就使用Dictionary作为缓存项目(而不是List),那么您可以避免在找到匹配项之前加载它的步骤。

答案 2 :(得分:0)

你要做的事实上是一个连接(在数据库意义上),特别是一个equi-join。您可以查看关于连接算法的this section of a Wikipedia article。上面列出的代码是嵌套循环连接,adymitruk的建议是散列连接,但正如Lou Franco评论的那样,最好的方法可能取决于您的集合有哪种排序或结构(如果有的话)。

如果searchItemCached只是一个无序列表,那么hash join可能是你最好的选择 - 只需从一个集合或另一个以ID作为密钥构建字典,然后循环遍历查找字典中匹配项的其他集合。如果searchItemCached已经是由ID键入的字典,那么散列连接绝对是您最好的选择。如果searchItemCachedsearchItemsNonCached都按ID排序,则可能需要sort-merge join

答案 3 :(得分:-1)

另一种方法是你可以编写一个linq表达式并在ID上加入两个列表,并使用更新的值创建相同类型的新对象。

from nc in searchItemsNonCached
join c in searchItemCached on nc.ID equals c.ID
select new (same type) // and assign the desc from c.Description