【问题标题】:C# Remove duplicates from two lists with multiple propertiesC# 从具有多个属性的两个列表中删除重复项
【发布时间】:2014-08-20 09:23:49
【问题描述】:

我想将随机元素插入现有数据库。在插入这些随机元素之前,我必须检查它们是否已经存在于数据库中(主键)。我不想添加额外的 ID 属性。

因此我想获取重复项,但只获取重复的主键,因此 .Union() 不起作用。

这里有两种解决方案:

var databaseList = database.Repository.GetAllElements();
foreach (var element in listOfRandomElements.Where(element => databaseList.Find(
                x =>
                x.Property0 == element.Property0 &&
                x.Property1 == element.Property1 &&
                x.Property2 == element.Property2)
                != null))
 {
     listOfElements.Remove(element);
 }


 listOfElements.RemoveAll(x => x.Property0 == databaseList.Select(y => true).Property0);

第一个解决方案不起作用,因为我想在枚举过程中删除元素。我可以通过解决方法 (Intelligent way of removing items from a List<T> while enumerating in C#) 解决这个问题,但对我来说,整个表达式看起来很糟糕。

第二个解决方案(最后一行代码)不存在,但类似的东西会很棒。

希望您有更好的解决方案,我想使用 LINQ。性能是次要的。

我想过合并两个列表并按主键分组,但是我必须删除已经在databaseList中的元素,但是我怎么知道databaseList中有哪些元素。

与往常一样,有数百种方法可以解决这个问题,至少我找到了一种(第一个解决方案有变通方法),但也许有更优雅的方法。

【问题讨论】:

    标签: c# linq merge union


    【解决方案1】:

    对于那些正在寻找完整解决方案的人。特别感谢@Christos!

    var databaseList = database.Repository.GetAllElements();
    var keys = databaseList.Select(x => new {x.key0, x.key1, x.key2}); 
    
    listOfElements.RemoveAll(
                    x =>
                    keys.Any(
                    k => k.key0 == x.key0 && 
                    k.key1 == x.key1 && 
                    k.key2 == x.key2 ));
    

    在这里找到提示:LINQ to Entities - where..in clause with multiple columns

    编辑:不必先提取密钥。可以使用完整的 databaseList 代替键。

    【讨论】:

      【解决方案2】:

      最初,您可以列出您已经拥有的所有 id:

      var ids = data.Repository.GetAllElements().Select(x=>x.Id);
      

      然后您可以简单地执行以下操作:

      foreach(var element in listOfRandomElements)
      {
          // Check if there isn't any id in the ids collection which is equal to element's id.
          if(!ids.Any(x=>x==element.Id)
              // Here you could insert your element.
      }
      

      更新

      listOfRandomElements.RemoveAll(x=>ids.Contains(x.Id));
      

      【讨论】:

      • 使用HashSet&lt;&gt; 比使用列表更好。
      • 谢谢!这看起来像是一个更具可读性的解决方案,但出于模块化原因,我不想立即插入它们,只删除它们。 (与我的第一个解决方案中的问题相同)。
      • @Olli1511 好吧。您可以在 if 语句中这样做,前提是您将更改 ids.Any 的否定。
      • 我认为这会导致 InvalidOperationException,因为您想在枚举时删除元素 -> 与我的解决方案中的问题相同 -> 需要解决方法。
      • @Christos 谢谢!我忘记了 .Contains() 方法。现在我只需要添加多个属性(复合主键),但我可以自己完成!谢谢帮助。
      猜你喜欢
      • 2015-07-20
      • 2018-05-16
      • 1970-01-01
      • 1970-01-01
      • 2020-07-25
      • 1970-01-01
      • 1970-01-01
      • 2011-04-25
      相关资源
      最近更新 更多