从嵌套对象中提取值并使用 LINQ 对它们进行排序

Posted

技术标签:

【中文标题】从嵌套对象中提取值并使用 LINQ 对它们进行排序【英文标题】:Extracting values from a nested object and sorting them using LINQ 【发布时间】:2021-08-16 12:01:09 【问题描述】:

我无法从一个相当复杂的对象中提取有用信息并对其进行排序。 这是它的简化版本:

他是班级:

class myClass

    public int id get; set; 
    public List<mySubClass> subClasses  get; set; 


class mySubClass

    public int offset  get; set; 
    public int value  get; set; 

这是一个初始化列表:

var mm = new List<myClass> 
    new myClass  id= 2,
        subClasses = new List<mySubClass> 
            new mySubClass  offset = 4, value = 3 ,
            new mySubClass  offset = 6, value = 5 ,
            new mySubClass  offset = 5, value = 4   ,
    new myClass  id= 2,
        subClasses = new List<mySubClass> 
            new mySubClass  offset = 20, value = 22 ,
            new mySubClass  offset = 1, value = 19   ,
    new myClass  id= 1,
        subClasses = new List<mySubClass> 
            new mySubClass  offset = 0, value = 1 ,
            new mySubClass  offset = 7, value = 6 ,
            new mySubClass  offset = 1, value = 2    ;
   

这是我尝试过的:

var oo = mm.OrderBy(y => y.id).SelectMany(yy => yy.subClasses.OrderBy(z => z.offset)).ToList().Select(y => y.value).ToArray();

我想要做的是将所有值提取到一个数组中并按“偏移”值对它们进行排序,但不会混淆不同的“id”。

不知何故,排序总是会变得一团糟。我认为我没有正确地对 id 进行分组,所有“列表”最终都被彼此独立对待。

预期输出应为:1,2,6,19,3,4,5,22 但我得到:1,2,6,3,4,5,19,22

编辑

在某些情况下,我也有兴趣恢复所有“mySubClass”对象。 因此,我们如何使用相同的排序标准返回一个“mySubClass”列表,而不是返回一个值数组?

【问题讨论】:

【参考方案1】:

您必须使用SelectMany,然后将属性存储在一个类型中,例如ValueTuple。然后很容易使用正确的OrderBy ...ThenBy

int[] result = mm
   .SelectMany(x => x.subClasses.Select(y => (Id:x.id, Offset:y.offset, Value:y.value)))
   .OrderBy(x => x.Id)
   .ThenBy(x => x.Offset)
   .Select(x => x.Value)
   .ToArray();

如果不是返回有序值,而是返回一个 基于相同排序标准的有序“mySubClass”列表。如何 你会这样做吗?

mySubClass[] result = mm
    .SelectMany(x => x.subClasses.Select(y => (Id:x.id, mySubClass:y)))
    .OrderBy(x => x.Id)
    .ThenBy(x => x.mySubClass.offset)
    .Select(x => x.mySubClass)
    .ToArray();

【讨论】:

谢谢,效果很好!我希望有一天能够理解这个 Linq 魔法:-) 如果不是返回有序值,而是希望返回基于相同排序标准的有序“mySubClass”列表,该怎么办。你会怎么做?谢谢【参考方案2】:

我想要做的是将所有值提取到一个数组中并按“偏移”值对它们进行排序

我认为您不想要仅包含属性 value 的值的整数数组。我想你想要一个序列:

int Id
int Offset
int Value

按 Offset 的升序排列。如果您不想在最终结果中出现Offset,您可以随时使用额外的Select 来摆脱它。

您是对的,您可以使用 Enumerable.SelectMany 的重载之一来执行此操作。我几乎总是使用带有参数resultSelector的重载

IEnumerable<MyClass> items = ...
var result = items.SelectMany(item => item.SubClasses,

// parameter resultSelector, use the [Item, SubClass] combination to make one new
(item, subclass) => new

    Id = item.Id,
    Offset = item.Offset,
    Value = item.Value,
)
.OrderBy(item => item.Offset);

【讨论】:

以上是关于从嵌套对象中提取值并使用 LINQ 对它们进行排序的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Linq C# 中使用嵌套字典对列表进行排序?

如何使用 LINQ 使用嵌套属性对列表进行排序

在列表中查找多个值并在新工作表中对它们进行排序

使用 C# 、 LINQ 进行排序

使用 LINQ 从具有嵌套数组的类中获取子属性值和父属性值

尝试使用递归从嵌套的 javascript 对象树中提取项目