使用Linq在集合之间添加,更新,删除

时间:2014-09-11 14:57:02

标签: c# wpf linq

这是我的情景。我正在使用WPF并使用双向绑定来显示每60秒从服务调用接收的集合对象。在第一次调用时,我创建了一组将从服务对象集合中显示的对象。在后续调用中,我需要将服务集合与现有集合进行比较,然后执行以下三项操作之一:

  1. 如果两个集合中都存在Item,则使用服务集合中对象的值更新Display集合中对象的所有值。
  2. 如果项目存在于服务集合而不是显示集合中,则将其添加到显示集合。
  3. 如果项目存在于显示集合中而不存在于服务集合中,则将其从“显示”集合中删除。
  4. 我正在寻找最佳方法。

    添加&除去 在这里进行左连接是否更聪明并且返回对另一方基本上唯一的一切,然后根据需要添加或删除它?

    我应该尝试联盟,因为Linq应该将两者合并而忽略重复吗? 如果是这样,它如何决定唯一性?它是在评估所有属性吗?我可以指定要合并的集合以及合并中要丢弃的集合吗?

    我是否应该使用Except来创建差异列表并以某种方式使用它?

    我应该使用Where / Not In逻辑创建一个新列表来添加和删除吗?

    更新 由于收藏品不是字典,因此进行比较的最佳方式是什么:

    list1.ForEach(x => list2[x.Id].SomeProperty = x.SomeProperty);
    

    除了指定与上面类似的每个属性值之外,是否有某种方法可以复制所有属性值?我可以在Linq中执行某种浅拷贝而不替换那里的实际对象吗?

    我不想只清除我的列表并每次重新添加所有内容,因为对象已绑定在显示中,并且我在属性中有逻辑,跟踪值随着值的变化而变化。

2 个答案:

答案 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并获取哈希码

Object.GetHashCode Method

然后你可以使用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);