【问题标题】:How to select items from two lists where the ids don't match如何从两个 ID 不匹配的列表中选择项目
【发布时间】:2012-08-01 02:39:42
【问题描述】:

好的,所以我有两个不同类型的项目列表。

var whales = new List<Whale>();

var crabs = new List<Crab>();

所以他们都有 id 属性。所以保存列表中的对象的 ID 为:

鲸鱼:1、3、4、5 螃蟹:1、2、3、4

好的,我有一个问题:

var matchedPairs = from c in crabs
                   from w in whales
                   where c.Id = w.Id
                   select new { crab = c, whale = w };

这样可以很好地获取匹配项。我遇到麻烦的地方是我想获得一份没有匹配鲸鱼的螃蟹列表,即。 Crab Id = 2。然后我想得到没有匹配螃蟹的鲸鱼,即 Whale Id = 5。

谁能告诉我如何编写这些查询?

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    如果您只想选择螃蟹。

    var result = crabs.Where(c => whales.All(w => w.Id != c.Id));
    

    【讨论】:

      【解决方案2】:

      可能是这样的:

      var unmatchedCrabs = from c in crabs
                           where !whales.Any(w => w.Id == c.Id)
                           select c;
      

      【讨论】:

      • 这是一个很好的答案,但事实证明我的螃蟹属于 IEnumerable 类型。当时不知道,所以没提。没有 Exists ,所以无法让它工作。
      • 好的......在这种情况下,有一个 Any 方法可以在 IEnumerable 上以相同的方式工作。我已经更新了我的答案以反映这一点。
      【解决方案3】:

      你想要一个outer join

      var crabsWithoutWhales = from c in crabs
                               join w1 in whales on c.Id equals w1.Id into ws
                               from w2 in ws.DefaultIfEmpty()
                               where w2 == null
                               select c;
      

      【讨论】:

        【解决方案4】:

        您可以从set operations 使用Union operation

        要使用它,您必须覆盖默认的Equality comparer and GetHashCode method。一旦你有了这些,你就可以做这样的事情:

        var matchedPair = crabs.Union(whales);
        

        在你的情况下,你应该有一个基类;例如具有平等比较器的动物。另一种选择是实现IEqualityComparer<>

        【讨论】:

        • 联合要求两个 Enumerable 的类型相同。 OP想要一些可以比较不同类型列表的东西。
        • 是的,但他可以使用带有 Equality 比较器的基类或实现 IEqualityComapere,即自定义比较器。
        • 没错,但是创建基类可能与业务场景无关……只为这个操作添加基类是一个糟糕的设计。
        • Union 的结果无论如何都不是我们想要的...... Union 会返回来自螃蟹的所有项目,即使它们存在于鲸鱼中。
        【解决方案5】:
        var result = crabs.SelectMany(c => whales, (c, w) => new { c, w })
                                      .Where(@t => whales.All(x => x.Id != t.c.Id) && crabs.All(x => x.Id != t.w.Id))
                                      .Select(@t => new {crab = @t.c, whale = @t.w});
        

        【讨论】:

          【解决方案6】:

          这是我能想到的最整洁的 LINQ,可以满足您的需求:

          var whalesOnly =
              from w in whales
              join c in crabs on w.Id equals c.Id into gcs
              where !gcs.Any()
              select w;
          
          var crabsOnly =
              from c in crabs
              join w in whales on c.Id equals w.Id into gws
              where !gws.Any()
              select c;
          

          你觉得这些怎么样?

          顺便说一句,您可以像这样更好地执行连接查询:

          var whalesAndCrabs =
              from whale in whales
              join crab in crabs on whale.Id equals crab.Id
              select new { crab, whale };
          

          【讨论】:

            【解决方案7】:

            您需要两个 Left Join by GroupJoin 方法,如下所示:

            var result1 = whales.GroupJoin(crabs, w => w.ID, c => c.ID, (w,cs) => new {WhaleID = w.ID, Matches = cs});
            var result2 = crabs.GroupJoin(whales, c => c.ID, w => w.ID, (c, ws) => new {CrabID = c.ID, Matches = ws});
            

            然后,根据您的需要过滤结果。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-05-26
              • 1970-01-01
              • 1970-01-01
              • 2019-03-15
              • 2023-03-24
              相关资源
              最近更新 更多