简体   繁体   English

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

[英]compare and update two lists in C#

The context is that I have one cached set of values in memory that were expensive to fetch, and another set of associated data that is inexpensive to fetch and can't be cached (business rule).上下文是我在 memory 中有一组缓存值,这些值的获取成本很高,而另一组关联数据的获取成本很低且无法缓存(业务规则)。 I've got it all working but I was just wondering if anyone could think of a less expensive way of doing this sort of update...我已经完成了所有工作,但我只是想知道是否有人能想到一种更便宜的方式来进行这种更新......

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

it's basically just to match up the cached information with the information I just got.它基本上只是将缓存的信息与我刚刚获得的信息进行匹配。 It all works and the load is almost negligable but I'm kind of a sucker for efficiency.一切正常,负载几乎可以忽略不计,但我有点效率低下。

EDIT: in the above, searchItemsNonCached and searchItemsCached are both Lists of SearchItem where Searchitem is a bespoke object.编辑:在上面,searchItemsNonCached 和 searchItemsCached 都是 SearchItem 的列表,其中 Searchitem 是定制的 object。

Store your cached items in a dictionary.将缓存的项目存储在字典中。 Now you can update only if the key exists.现在您只能在密钥存在时进行更新。

Load a Dictionary with the cached items and then cycle through each non-cached item looking for a match in the dictionary.加载包含缓存项的Dictionary ,然后在每个非缓存项中循环查找字典中的匹配项。 This is O(n) as opposed to the nested loop which is O(n^2) .这是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;
  }
}

If you could consider using a Dictionary for the cached items from the beginning (instead of a List ) then you could avoid the step of loading it before finding matches.如果您可以考虑从一开始就为缓存项目使用Dictionary (而不是List ),那么您可以避免在查找匹配项之前加载它的步骤。

What you're trying to do is essentially a join (in the database sense), specifically an equi-join.你想要做的本质上是一个连接(在数据库意义上),特别是一个等连接。 You might check out this section of a Wikipedia article on join algorithms.您可以查看有关连接算法的 Wikipedia 文章的这一部分 The code you listed above is a nested-loop join, and adymitruk's suggestion is a hash join, but as Lou Franco commented, the best approach probably depends on what kind of ordering or structure (if any) your collections have.您上面列出的代码是嵌套循环连接,adymitruk 的建议是 hash 连接,但正如 Lou Franco 评论的那样,最好的方法可能取决于您的 collections 有什么样的排序或结构(如果有)。

If searchItemCached is just an unordered list, then a hash join is probably your best bet--just build a dictionary from one collection or the other with the ID as the key, then loop through the other collection looking up the matching items from the dictionary.如果searchItemCached只是一个无序列表,那么hash 连接可能是您最好的选择——只需从一个集合或另一个集合中构建一个字典,并将 ID 作为键,然后遍历另一个集合,从字典中查找匹配项. If searchItemCached is already a dictionary keyed by ID, then a hash join is definitely your best bet.如果searchItemCached已经是一个以 ID 为键的字典,那么 hash 连接绝对是您最好的选择。 If searchItemCached and searchItemsNonCached are both sorted by ID, then a sort-merge join is probably the way to go.如果searchItemCachedsearchItemsNonCached都按 ID 排序,那么排序合并连接可能是 go 的方式。

Another approach is you can write a linq expression and join the two lists on ID, and create new objects of same type with updated values.另一种方法是您可以编写一个 linq 表达式并加入 ID 上的两个列表,并创建具有更新值的相同类型的新对象。

ex前任

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM