【问题标题】:Update a List<T> witha SubList<T> performance (LINQ or Not)更新具有 SubList<T> 性能的 List<T>(LINQ 与否)
【发布时间】:2014-01-06 12:56:24
【问题描述】:

我有一个可以包含 ~200'000 项的列表。我需要使用子列表更新固定数量的字段,例如 150 个项目。这是我现在使用的代码:

listItem:200'000 个项目列表 - subListItem:150 个项目列表(更新)

listItem.Select(item =>
{
    if (subListItem.Exists(x => x.ID == item.ID))
    {
        var currentItem = subListItem.Single(x => x.ID == item.ID);
        item.FIELD_1 = currentItem.FIELD_1;
        item.FIELD_2 = currentItem.FIELD_2;
        item.FIELD_3 = currentItem.FIELD_3;
        item.FIELD_4 = currentItem.FIELD_4;
    }

    return item;
}).ToList();

这很好用,但性能真的很差。你有什么建议吗?

更新的解决方案:

dictItem = listItem.ToDictionary(x => x.ID);

foreach (Item updatedItem in subListItem)
{
    Item originalItem = dictItem[updatedItem.ID];
    originalItem.FIELD_1 = updatedItem.FIELD_1;
    originalItem.FIELD_2 = updatedItem.FIELD_2;
    originalItem.FIELD_3 = updatedItem.FIELD_3;
    originalItem.FIELD_4 = updatedItem.FIELD_4;
    dictItem[updatedItem.ID] = originalItem;
}

【问题讨论】:

  • @haim770 是的,它是 Linq to Objects

标签: c# linq list generics updates


【解决方案1】:

利用字典使项目查找更快,即

var subListItemsById = subListItems.ToDictionary(x => x.ID);
foreach(var item in listItem)
{
    SubListItem subListItem;
    if(subListItemsById.TryGetValue(item.ID, out subListItem))
    {
        item.FIELD_1 = subListItem.FIELD_1;
        item.FIELD_2 = subListItem.FIELD_2;
        item.FIELD_3 = subListItem.FIELD_3;
        item.FIELD_4 = subListItem.FIELD_4;
    }
}

您原来的listItem 将包含修改后的对象。这仅在 listItem 中包含的项目是引用类型时才有效。如果它们是可变结构,您将需要执行与您的示例类似的操作:

var subListItemsById = subListItems.ToDictionary(x => x.ID);
var modifiedItems =  listItem.Select(item =>
{
    SubListItem subListItem;
    if(subListItemsById.TryGetValue(item.ID, out subListItem))
    {
        item.FIELD_1 = subListItem.FIELD_1;
        item.FIELD_2 = subListItem.FIELD_2;
        item.FIELD_3 = subListItem.FIELD_3;
        item.FIELD_4 = subListItem.FIELD_4;
    }
    return item;
}).ToList();

【讨论】:

  • 如果原始容器被优化为使用字典会更好。这优化了 150x 查找,优化 200.000x 查找会更快。
  • 如果字典使用正确的初始容量进行初始化,这两种方法的性能肯定是一样的吗?
  • 使用字典来解决它以获得最大的列表。查看原始帖子以获取解决方案
  • 在我的 LINQPad 测试中,我发现使用具有较小集合的 ToDictionary 时性能更好,而使用具有正确初始容量的字典时性能大致相同。
【解决方案2】:

如果您需要更好的性能,则需要使用针对查找进行了优化的容器。例如 Dictionary 使用您的 ID 作为键。

【讨论】:

    【解决方案3】:

    您可以通过按说明创建字典来加快速度。但是,如果您不必创建副本,也可以保留原始列表,从而减少内存占用。

    var subItemLookup = subItems.ToDictionary(i => i.Id);
    
    foreach (var item in items)
    {
        SubItem subItem;
        if (subItemLookup.TryGetValue(item.Id, out subItem))
        {
            item.Field1 = subItem.Field1;
            //etc.
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多