【问题标题】:Advanced LINQ filtering高级 LINQ 过滤
【发布时间】:2019-05-10 10:40:35
【问题描述】:

我在使用 LINQ 进行高级过滤数据时遇到问题。

我想获取带有详细信息列表的计划类列表,其中项目列表中的参数包含特定字符。此外,Items 列表应仅包含此过滤后的元素。

我的课程如下所示:

class Plan
{
    public string Name { get; set; }
    public List<Detail> Details { get; set; }

    public Plan()
    {
        Details = new List<Detail>();
    }
}

class Detail
{
    public string Setting { get; set; }

    public List<Item> Items { get; set; }

    public Detail()
    {
        Items = new List<Item>();
    }
}

class Item
{
    public string Arguments { get; set; }
}

我当前的解决方案如下所示,但我认为这不是最佳选择。我尝试使用WhereAny 编写此代码,但我有计划列表,其中项目包含所有项目。

var filteredPlans = plans.Select(x =>
            new Plan
            {
                Name = x.Name,
                Details = x.Details.Select(y =>
                    new Detail
                    {
                        Setting = y.Setting,
                        Items = y.Items.Where(c => c.Arguments.Contains("...")).Select(z =>
                              new Item
                              {
                                  Arguments = z.Arguments
                              }).ToList()
                    }).ToList()
            });

如何使用 WHERE 语句编写此代码或最好的解决方案是什么?

另外,如何使用基于项目列表的 LINQ EXPECT 获得收获差异?例如计划:包含所有带有项目的计划,计划2:包含所有带有过滤项目的计划,计划3应该包含所有不属于计划2的计划。

【问题讨论】:

  • 你能提供一些示例输入和预期输出吗?
  • 您的解决方案似乎总是为您提供全套计划,但如果Arguments 不匹配,那么List&lt;Item&gt; Items 就是空的。这是期望的结果吗?
  • " 带有详细信息列表,其中项目列表中的参数包含特定字符。"这是否意味着如果项目列表包含特定字符,那么 Detail 也不应该再出现在列表中?
  • 是的,这是理想的结果。如果项目不包含特定字符,则项目列表应为空,并且详细信息列表应包含这些列表。
  • @MongZhu plansfilteredPlans 的主要区别在于项目列表。

标签: c# performance linq collections


【解决方案1】:

这对你有用吗?

首先,我仅限于其任何详细信息包含与过滤器匹配的任何项目的计划。

然后我将每个计划的详细信息限制为仅包含与过滤器匹配的任何项目的那些人

然后我限制每个计划的项目

    private List<Plan> FilteredPlans(List<Plan> plans, string filter)
    {
        List<Plan> filteredPlans = plans.Where(plan => plan.Details.Any(detail => detail.Items.Any(item => item.Arguments.Contains(filter)))).ToList();

        foreach (var plan in filteredPlans)
        {
            plan.Details = plan.Details.Where(detail => detail.Items.Any(item => item.Arguments.Contains(filter))).ToList();

            foreach (var detail in plan.Details)
            {
                detail.Items = detail.Items.Where(item => item.Arguments.Contains(filter)).ToList();
            }
        }

        return filteredPlans;
    }

另外,这里有另一个版本作为单个语句,但我认为它的可读性要差得多。我基本上是先限制物品,然后向后工作,只保留非空的容器

    private List<Plan> FilteredPlansWithSelect(List<Plan> plans, string filter)
    {
        List<Plan> filteredPlans = plans.Select(plan => 
        new Plan()
        {
            Name = plan.Name,
            Details = plan.Details.Select(detail =>
                new Detail()
                {
                    Setting = detail.Setting,
                    Items = detail.Items.Where(item => item.Arguments.Contains(filter)).ToList()
                }).Where(detail => detail.Items.Count > 0).ToList()
        }).Where(plan => plan.Details.Count > 0).ToList();


        return filteredPlans;
    }

为语法编辑

【讨论】:

    猜你喜欢
    • 2023-04-08
    • 2019-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-08
    • 2016-08-16
    • 2012-07-24
    • 1970-01-01
    相关资源
    最近更新 更多