Reputation: 171
I am having trouble extracting useful information and order them from a rather complex object.
Here is a simplified version of it:
He are the classes:
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; }
}
Here is an initialised list:
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 } } } };
Here is what I have tried:
var oo = mm.OrderBy(y => y.id).SelectMany(yy => yy.subClasses.OrderBy(z => z.offset)).ToList().Select(y => y.value).ToArray();
What am I trying to do is to extract all the values into an array and sorting them by "offset" value, but without mixing up the different "id".
Somehow, the ordering always ends up getting messed up. I think I am not grouping id's properly and all the "List< mySubClass >" end up getting treated independently from one another.
Expected output should be: 1,2,6,19,3,4,5,22 But I am getting: 1,2,6,3,4,5,19,22
In some case, I am also interested in recovering all the "mySubClass" objects.
Therefore, instead of returning an array of values, how could we return a list of "mySubClass" using the same sorting criteria?
Upvotes: 1
Views: 639
Reputation: 460278
You have to use SelectMany
and then store the properties in a type, for example a ValueTuple
. Then it's easy to use the proper 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();
What if instead of returning the ordered values you wanted to return a list of ordered "mySubClass" based on the same sorting criteria. How would you do that?
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();
Upvotes: 5
Reputation: 30512
What am I trying to do is to extract all the values into an array and sorting them by "offset" value
I think you don't want the integer array of only the values of property value
. I think you want a sequence of:
int Id
int Offset
int Value
Ordered by ascending value of Offset. If you don't want Offset
in your end-result, you can always use an extra Select
to get rid of it.
You are right, you do this with one of the overloads of Enumerable.SelectMany. I almost always use the overload that has a parameter 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);
Upvotes: 1