这是我的情景。我正在使用WPF并使用双向绑定来显示每60秒从服务调用接收的集合对象。在第一次调用时,我创建了一组将从服务对象集合中显示的对象。在后续调用中,我需要将服务集合与现有集合进行比较,然后执行以下三项操作之一:
我正在寻找最佳方法。
添加&除去 在这里进行左连接是否更聪明并且返回对另一方基本上唯一的一切,然后根据需要添加或删除它?
我应该尝试联盟,因为Linq应该将两者合并而忽略重复吗? 如果是这样,它如何决定唯一性?它是在评估所有属性吗?我可以指定要合并的集合以及合并中要丢弃的集合吗?
我是否应该使用Except来创建差异列表并以某种方式使用它?
我应该使用Where / Not In逻辑创建一个新列表来添加和删除吗?
更新 由于收藏品不是字典,因此进行比较的最佳方式是什么:
list1.ForEach(x => list2[x.Id].SomeProperty = x.SomeProperty);
除了指定与上面类似的每个属性值之外,是否有某种方法可以复制所有属性值?我可以在Linq中执行某种浅拷贝而不替换那里的实际对象吗?
我不想只清除我的列表并每次重新添加所有内容,因为对象已绑定在显示中,并且我在属性中有逻辑,跟踪值随着值的变化而变化。
答案 0 :(得分:1)
您可以使用except和intersect方法来完成您要执行的大部分操作。
但是,根据对象的大小,这可能会占用大量资源。
我会推荐以下内容。
var listIDsA = collectionA.Select(s => s.Id).Distinct().ToList();
var listIDsB = collecitonB.Select(s => s.Id).Distinct().ToList();
var idsToRemove = listIDsB.Select (s => !listIDsA.Contains(s.Id)).ToList();
var idsToUpdate = listIDsB.Select(s => listIDsA.Contains(s.Id)).ToList();
var idsToAdd = listIDsA.SelecT(s => !listIDsB.Contains(s.Id)).ToList();
然后使用这三个新集合,您可以添加/删除/更新适当的记录。
您还可以使用hashedset而不是IEnumerables来获得更好的性能。这将要求您创建扩展类以添加该功能。以下是如何做到这一点的一个很好的解释(它并不复杂)。
How to convert linq results to HashSet or HashedSet
如果这样做,则需要将前两行中的.ToList()替换为.ToHasedSet()
答案 1 :(得分:1)
为了进行比较,您需要覆盖equals并获取哈希码
然后你可以使用List.Contains
List.Contains Method
如果您可以使用HashSet,那么您将获得更好的性能
未经过测试的代码
ListDisplay.Remove(x => !ListSerice.Contains(x));
Foreash(ListItem li in ListDisplay)
{
ListItem lis = ListSerice.FirstOrDefault(x => x.Equals(li));
if (lis == null) continue;
// perform update
}
Foreach(ListItem li in ListSerice.Where(x => !ListDisplay.Contains(x))) ListDisplay.Add(li);