使用 LINQ 将一个对象列表属性更新为其他列表

本文关键字:列表 更新 其他 属性 使用 一个对象 LINQ | 更新日期: 2023-09-27 18:18:29

>我有一个场景,比如思考

class a 
{
  String Username;
  String val;
}

 List<a> lst = new List<a>();
 List<a> lstnew = new List<a>();

我需要的是,lstnew我在val属性(仅在多个对象中(中有一些更新的值,我需要的是使用 LINQ 使用 LINQ 作为Username属性lstnew更新lst

使用 LINQ 将一个对象列表属性更新为其他列表

您可以在 UserName 上联接两个列表,然后将第一个列表中的Value更新为第二个列表中的列表。

例如,给定此类和列表:

public class a
{
    public string UserName { get; set; }
    public string Value { get; set; }
}
List<a> list = new List<a>
{
    new a { UserName = "Perry", Value = "A" },
    new a { UserName = "Ferb", Value = "B" },
    new a { UserName = "Phineas", Value = "C" }
};
List<a> newList = new List<a>
{
    new a { UserName = "Phineas", Value = "X" },
    new a { UserName = "Ferb", Value = "Y" },
    new a { UserName = "Candace", Value = "Z" }
};

您可以联接以获取具有共同UserName的元素:

var common = from a1 in list
             join a2 in newList on a1.UserName equals a2.UserName
             select new { A1 = a1, A2 = a2 };

此时,如果我理解正确,您希望更新原始列表中的元素:

foreach(var c in common)
{
    c.A1.Value = c.A2.Value;
}

此时,list中的元素如下所示:

UserName    Value
-----------------
Perry       A
Ferb        Y
Phineas     X

听起来你有两个列表。 其中一个名为 lst 并包含用户名的完整列表,另一个名为 lstnew 的用户名包含已更新其val属性的用户名列表。 我建议将未触及的用户名与已更新的用户名合并。 这是我能想到的对 LINQ 最友好的解决方案。

var updatedList = Enumerable.Union(
    lst.Where(x => !lstnew.Any(y => y.Username == x.Username)),
    lstnew).ToList();

您应该能够使用 .Zip() 方法来执行此操作。

lst.Zip(lstNew, (orig, new) => {
    orig.Username = new.Username;
    return orig;
});

您将每对放在一起的想法,然后不是返回新的,而是更改orig.Username值并返回orig

这也应该可以解决问题。 由 Alastair Pitts 提出的Zip方法假设两个集合具有相同的元素顺序,并且第一个列表中的每个元素在第二个列表中都有相应的元素。我的方法更通用,它只是通过比较属性来查找相应的元素Username。它仍然假设对于lstNew中的每个元素,lst中都有相应的元素。

lstNew.ForEach(new => lst.First(orig => orig.Username == new.Username).val = new.val);
我知道

这是一个老问题,但我开发了一个更优雅的解决方案,这比@JeffOgata给出的解决方案略有改进:

var newList= lst.GroupJoin(lstnew ,
                i => i.UserName ,
                j => j.UserName ,
                (i, j) => j.FirstOrDefault()?? i );

其中lst是原始列表,lstnew是新列表。

这将只是将第一个列表中的整个对象替换为第二个列表中的相应对象(如果存在(。这比@JeffOgata给出的答案略有改进

结果是一样的。

如果您有复杂的对象,那么遍历每个对象然后遍历所有属性是一个问题,简单地用新对象替换旧对象会更快。

希望这会帮助某人。