使用 Linq 一次更新可观察集合项的两个字段
Posted
技术标签:
【中文标题】使用 Linq 一次更新可观察集合项的两个字段【英文标题】:Updating two fields of an observable collection item at once using Linq 【发布时间】:2018-11-22 03:20:07 【问题描述】:我有两个相同类型的 Observable Collection 列表:
ObservableCollection<MyDataModel> source;
ObservableCollection<MyDataModel> target;
假设它们已经被填充,所以我尝试从源更新目标,但只有两个字段和第一个匹配的项目(我想保持其余字段不可触及):
foreach (var s in source)
target.First(t => t.Id == s.Id).Id = s.Id;
target.First(t => t.Id == s.Id).Desc = s.Desc;
我的模特:
public class MyDataModel
public int Id get; set;
public string Desc get; set;
public string Country get; set;
public string PostalCode get; set;
在上面的 foreach 中,我重复了 target.First 两次,我想避免这种情况并立即执行。是否可以使用 Linq?
【问题讨论】:
为什么你不能直接var current = target.First(t => t.Id == s.Id);
然后用current
做任何你想做的事?
【参考方案1】:
您可以简单地执行一次First()
并将结果分配给一个变量。
foreach (var s in source)
var item = target.First(t => t.Id == s.Id);
item.Id = s.Id;
item.Desc = s.Desc;
此外,由于您查找项目的条件是 id 是否匹配,因此您实际上并不需要 item.Id = s.Id;
步骤。
编辑
但是,如果在目标中找不到该项目,则上述代码可能会引发异常。这将是一个更好的方法:
foreach (var s in source)
var item = target.Where(t => t.Id == s.Id).FirstOrDefault();
if (item != null)
item.Id = s.Id;
item.Desc = s.Desc;
【讨论】:
哦,@Federico 在 cmets 中击败了我。【参考方案2】:简单回答:
foreach (var s in source)
var t = target.First(x => x.Id == s.Id);
t.Desc = s.Desc;
t.Country = s.Country;
简单的答案是 O(source * target) 操作。使用字典可以将性能提高到 O(source + target):
var sourceDict = source.ToDictionary(s => s.Id);
foreach (var t in target)
MyDataModel s;
if (sourceDict.TryGetValue(t.Id, out s))
t.Desc = s.Desc;
t.Country = s.Country;
【讨论】:
以上是关于使用 Linq 一次更新可观察集合项的两个字段的主要内容,如果未能解决你的问题,请参考以下文章