【问题标题】:如何使用 linq 来“扁平化”层次结构?
【发布时间】:2022-01-23 14:54:42
【问题描述】:

鉴于以下代码示例,我该怎么做:

  1. 让未过滤列表中注释掉的行生效(不更改 Result 的定义)?
  2. 让过滤列表中被注释掉的行起作用(不改变结果的定义)?从我的数学来看,它应该给出 32 条记录。希望我的输出意图足够清晰,让其他人理解

有什么问题可以问

问候

凯尔

    //Populate data
    var alphas = new List<Alpha>();
    
    for (int a = 1; a <= 10; a++)    
    {
       var alpha = new Alpha() { Id = a, Name = "A" + a };

       for (int b = 1; b <= 10; b++)
       {
         var beta = new Beta() { Id = b, Name = "B" + b };

         for (int c = 1; c <= 10; c++)
         {
            var charlie = new Charlie() { Id = c, Name = "C" + c };

            for (int d = 1; d <= 10; d++)
            {
                var delta = new Delta() { Id = d, Name = "D" + d };

                charlie.Deltas.Add(delta);
            }
            beta.Charlies.Add(charlie);
        }
        alpha.Betas.Add(beta);
       }    
      alphas.Add(alpha);
    }

//Get results into required format without filtering
var unfilteredResults = alphas.Select(a => new Result
{
    AId = a.Id,
    AName = a.Name,

    //BId = a.Betas.Select(b => b.Id),
    //BName = a.Betas.Select(b => b.Name),

    //CId = a.Betas.Select(b => b.Charlies.Select(c => c.Id)),
    //CName = a.Betas.Select(b => b.Charlies.Select(c => c.Name)),

    //DId = a.Betas.Select(b => b.Charlies.Select(c => c.Deltas.Select(d => d.Id))),
    //DName = a.Betas.Select(b => b.Charlies.Select(c => c.Deltas.Select(d => d.Name)))
});


var whiteListAIds = new List<int>() { 1, 2 };
var whiteListBIds = new List<int>() { 3, 4 };
var whiteListCIds = new List<int>() { 5, 6 };
var whiteListDIds = new List<int>() { 7, 8 };

//Get results into required format with filtering
var filteredResults = alphas.Where(a => whiteListAIds.Contains(a.Id)).Select(a => new Result
{
    AId = a.Id,
    AName = a.Name,

    //BId = a.Betas.Where(b => whiteListBIds.Contains(b.Id)).Select(b => b.Id),
    //BName = a.Betas.Where(b => whiteListBIds.Contains(b.Id)).Select(b => b.Name),

    //CId = a.Betas.Where(b => whiteListBIds.Contains(b.Id)).Select(b => b.Charlies.Where(c => whiteListCIds.Contains(c.Id)).Select(c => c.Id)),
    //CName = a.Betas.Where(b => whiteListBIds.Contains(b.Id)).Select(b => b.Charlies.Where(c => whiteListCIds.Contains(c.Id)).Select(c => c.Name)),

    //DId = a.Betas.Where(b => whiteListBIds.Contains(b.Id)).Select(b => b.Charlies.Where(c => whiteListCIds.Contains(c.Id)).Select(c => c.Deltas.Where(d => whiteListDIds.Contains(d.Id)).Select(d => d.Id))),
    //DName = a.Betas.Where(b => whiteListBIds.Contains(b.Id)).Select(b => b.Charlies.Where(c => whiteListCIds.Contains(c.Id)).Select(c => c.Deltas.Where(d => whiteListDIds.Contains(d.Id)).Select(d => d.Name)))
});

class Alpha
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Beta> Betas { get; set; } = new List<Beta>();
}

class Beta
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Charlie> Charlies { get; set; } = new List<Charlie>();
}

class Charlie
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Delta> Deltas { get; set; } = new List<Delta>();
}

class Delta
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class Result
{
    public int AId { get; set; }
    public string AName { get; set; }

    public int BId { get; set; }
    public string BName { get; set; }

    public int CId { get; set; }
    public string CName { get; set; }

    public int DId { get; set; }
    public string DName { get; set; }

}

【问题讨论】:

  • 试试 selectMany()

标签: c# linq


【解决方案1】:

感谢第一个答案linq selectmany flatten multiple levels,它可以按如下方式工作

基本上必须将“外部”父母的 .SelectMany() 和最后一个/内部孩子的 .Select() 结合起来。

//Populate data
var alphas = new List<Alpha>();

for (int a = 1; a <= 10; a++)
{
    var alpha = new Alpha() { Id = a, Name = "A" + a };

    for (int b = 1; b <= 10; b++)
    {
        var beta = new Beta() { Id = b, Name = "B" + b };

        for (int c = 1; c <= 10; c++)
        {
            var charlie = new Charlie() { Id = c, Name = "C" + c };

            for (int d = 1; d <= 10; d++)
            {
                var delta = new Delta() { Id = d, Name = "D" + d };

                charlie.Deltas.Add(delta);
            }
            beta.Charlies.Add(charlie);
        }
        alpha.Betas.Add(beta);
    }

    alphas.Add(alpha);
}   


var unfilteredResults = alphas.SelectMany(a => a.Betas.SelectMany(b=> b.Charlies.SelectMany(c=> c.Deltas.Select(d => new Result
{
    AId = a.Id,
    AName = a.Name,

    BId = b.Id,
    BName = b.Name,

    CId = c.Id,
    CName = c.Name,

    DId = d.Id,
    DName = d.Name
}))));


var whiteListAIds = new List<int>() { 1, 2 };
var whiteListBIds = new List<int>() { 3, 4 };
var whiteListCIds = new List<int>() { 5, 6 };
var whiteListDIds = new List<int>() { 7, 8 };

//Get results into required format with filtering
var filteredResults = unfilteredResults.Where(r => whiteListAIds.Contains(r.AId) && whiteListBIds.Contains(r.BId) && whiteListCIds.Contains(r.CId) && whiteListDIds.Contains(r.DId));

Console.WriteLine("Finished");

class Alpha
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Beta> Betas { get; set; } = new List<Beta>();
}

class Beta
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Charlie> Charlies { get; set; } = new List<Charlie>();
}

class Charlie
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Delta> Deltas { get; set; } = new List<Delta>();
}

class Delta
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class Result
{
    public int AId { get; set; }
    public string AName { get; set; }

    public int BId { get; set; }
    public string BName { get; set; }

    public int CId { get; set; }
    public string CName { get; set; }

    public int DId { get; set; }
    public string DName { get; set; }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-14
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    • 2021-01-01
    相关资源
    最近更新 更多