【问题标题】:LINQ with AND or OR for 2 or more enumerable lists带有 AND 或 OR 的 LINQ 用于 2 个或更多可枚举列表
【发布时间】:2015-10-29 02:15:16
【问题描述】:

所以我有 2 个不同的列表,比如服务和组。组包含服务。我正在尝试找出它们之间的 linq 连接。我有一个允许用户选择一项或多项服务的界面,我需要一个查询来选择其中包含所有选定服务的所有组,或其中至少包含一项选定服务的所有组.和/或段是通过无线电选择的。

var servFilter = from cs in lstServices.CheckedItems.Cast<ListViewItem>()
                         join ts in TotalServices on cs.Tag equals ts.IDserv
                         join fg in groupSet on ts.IDpack equals fg.IDPack
                         select fg;

这就是我目前所拥有的,并且似乎正在处理它的“或”方面,我只是无法理解我将如何“和”这个。

为清楚起见: 假设我有 Group1 和 2,以及 Service1,2 和 3。Group1 有服务 1 和 3。Group2 有服务 1 和 2。如果您选择了服务 1 和 2,那么现在的代码方式是您将获得两个组(或者,两个组都包含服务 1,不一定包含服务 2)。我正在寻找一个只会给我组 2 的查询,因为它是唯一同时包含服务 1 和服务 2 的组

【问题讨论】:

  • 您的代码中的“组”在哪里?
  • @DLeh packFilter,为清楚起见,仅对 groupSet 进行了编辑
  • 您需要两个查询。全部和至少一个不能合并。
  • @jdweng 是的,我明白了,我只是想不通如何将“和”查询放在一起。加入只会给我或,那么我将如何加入以获得“和”?
  • 你的意思是Concat() 还是Union() 将它们放到一个列表中?

标签: c# linq


【解决方案1】:

试试这个:

 var query = (from g in groupSet
              join s in TotalServices on g.IDpack equals s.IDpack
              group new {s, g} by g into grp
              select new
              {
                 Group = grp.Key,
                 Services = grp
              }).Where(x => !lstServices.CheckedItems.Cast<ListViewItem>().Select(x1 => x1.Tag).Except(x.Services.Select(x2 => x2.Services.IDserv)).Any()).Select(a => a.Group).ToList();

其实你不需要select new,这里有更好看的代码:

var query = (from g in groupSet
             join s in TotalServices on g.IDpack equals s.IDpack
             group new { s, g } by g into grp
             where !lstServices.CheckedItems.Cast<ListViewItem>().Select(x1 => x1.Tag).Except(grp.Select(x2 => x2.s.IDserv)).Any()
             select grp.Key).ToList();

【讨论】:

  • 我会对此进行调查,但要澄清一下,假设我有 Group1 和 2,以及 Service1,2 和 3。Group1 有服务 1 和 3。Group2 有服务 1 和 2。如果你选择服务 1 和 2,代码的方式现在您将获得两个组(或者,两个组都包含服务 1)。我正在寻找一个只会给我组 2 的查询,因为它是唯一同时包含服务 1 和服务 2 的组。
  • 这似乎不起作用。只是不返回任何结果。 Groups 和 Services 是 Model Objects,contains 正在寻找一个 ListViewItem,我动态地创建了它们,所以要使用 contains,我必须使用与其他相同的约定(基本上只是名称)与新创建的 LVI 进行比较ID 在控制标签中的组)。它似乎无法找到任何东西。 servFilter.ToArray() 只返回 0 个元素,无论我选择了多少服务,或者它们属于哪个组。
  • 我最终能够在控制台应用程序中返回一些结果,但它仍然给了我两个组,而不仅仅是一个组(OR 条件)。
  • 很高兴能提供帮助,不过我做了一些改进。你应该检查一下。
【解决方案2】:

你可以这样做:

var selectedServiceIds = lstServices.CheckedItems.Cast<ListViewItem>().Select(cs => cs.Tag);

var anySelected = groupSet.Where(fg => TotalServices.Any(
    ts => ts.IDpack == fg.IDPack && selectedServiceIds.Contains(ts.IDserv)));

var allSelected = groupSet.Where(fg => selectedServiceIds.All(
    id => TotalServices.Any(ts => ts.IDpack == fg.IDPack && ts.IDserv == id)));

【讨论】:

  • 这种作品。经过一些测试后,我看到了: 如果我有:G1 - S1, S3 G2 - S1, S2 G3 - S1, S2, S3 SelectedService = 1, 2 Gives: G2 Expected: G2, G3 SelectedService = 1, 3 Gives: G1预期:G1、G3 SelectedService = 1、2、3 给出:G1、G2、G3 预期:G3
  • SelectedService = 2, 3 Gives: null Expected: G3
  • @ZexksMarquise 是的,我搞砸了一些条件。请参阅更新,它很简单且一目了然 - 每个选定的项目都必须有一个相应的组服务才能包含该组。
猜你喜欢
  • 2021-12-08
  • 2017-07-29
  • 1970-01-01
  • 2011-01-08
  • 2012-09-05
  • 1970-01-01
  • 2021-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多