【问题标题】:Update a property field in a List更新列表中的属性字段
【发布时间】:2021-06-29 03:07:59
【问题描述】:

我有一个List<Map>,我想根据来自另一个List<Map> 的匹配值更新Map.Target 属性。

基本上,逻辑是:

If mapsList1.Name is equal to mapsList2.Name
    Then mapsList1.Target = mapsList2.Name

Map 类的结构如下所示:

public class Map {
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Target { get; set; }
}

我尝试了以下方法,但显然它不起作用:

List<Map> mapsList1 = new List<Map>();
List<Map> mapsList2 = new List<Map>();
    
// populate the 2 lists here
    
mapsList1.Where(m1 => mapsList2.Where(m2 =>  m1.Name == m2.Name) ) // don't know what to do next

列表 1 中的项目数将始终大于或等于列表 2 中的项目数。两个列表中没有重复项。

【问题讨论】:

标签: c#


【解决方案1】:

假设列表中有少量项目,列表 1 中只有一项匹配:

list2.ForEach(l2m => list1.First(l1m => l1m.Name == l2m.Name).Target = l2m.Target);

如果 List1 中有多个项目必须更新,请枚举整个 list1,在 list2 上执行 First。

list1.ForEach(l1m => l1m.Target = list2.FirstOrDefault(l2m => l1.Name == l2m.Name)?.Target ?? l1m.Target);

如果list2中有大量item,则转成字典

var d = list2.ToDictionary(m => m.Name);
list1.ForEach(m => m.Target = d.ContainsKey(m.Name) ? d[m.Name].Target : m.Target);

(大概list2不包含任何重复的名字)

如果 list1 的名称是唯一的,并且 list2 中的所有内容都在 list1 中,您甚至可以将 list1 变成字典并枚举 list2:

var d=list1.ToDictionary(m => m.Name);
list2.ForEach(m => d[m.Name].Target = m.Target);

如果 List 2 有不在 list1 中的条目或 list1 有重复的名称,您可以使用 Lookup 代替,您只需要做一些事情来避免“集合已修改;枚举可能无法执行”你会如果您试图修改它返回的列表以响应名称

mapsList1.Where(m1 => mapsList2.Where(m2 => m1.Name == m2.Name) ) // 不知道下一步该做什么

LINQ Where 并没有真正像那样工作/这本身不是一个声明。 m1 是来自 list1 的条目,内部 Where 将产生列表 2 项的可枚举,但它不会导致外部 Where 期望的布尔值,也不能对任何一个序列执行任何操作,因为 LINQ 操作是不应该有副作用。你可以对 Where 做的唯一事情是捕获或使用它在其他操作中返回的序列(比如枚举它),所以 Where 并不是你真正用于此操作的东西,除非你用它来查找所有对象你需要改变。可能值得指出的是,ForEach 是一个列表的东西,而不是一个 LINQ 的东西,基本上只是另一种写法foreach(var item in someList)

【讨论】:

  • 列表 1 中的项目将始终等于或大于列表 2 中的项目
  • 欢迎您! list1 和 list 2 大概有多少项?
  • 每个列表最多可以有 1,048,576 个。清单 1 永远不会有重复项。
  • 根据提到的警告(名称中没有重复),我肯定会将 list1 变成字典并枚举 list2。如果 list2 不是一个完美的子集(即它可能包含一个不在 list1 中的项目),那么您将需要一个 ContainsKey 或 TryGetValue 以避免异常;如果您需要一些指针,请告诉我
  • 好的,会的。再次感谢您,感谢您的帮助
【解决方案2】:

如果集合足够大,更好的方法是创建一个字典来查找目标:

List<Map> mapsList1 = new List<Map>();
List<Map> mapsList2 = new List<Map>();
var dict = mapsList2
    .GroupBy(map => map.Name)
    .ToDictionary(maps => maps.Key, maps => maps.First().Target);
foreach (var map in mapsList1)
{
    if (dict.TryGetValue(map.Name, out var target))
    {
        map.Target = target;
    }
}

请注意,这将丢弃来自mapsList2 的任何可能重复的名称。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-12
    • 1970-01-01
    • 2020-07-11
    • 1970-01-01
    • 2011-05-22
    • 2017-08-11
    相关资源
    最近更新 更多