X3074861X
X3074861X

Reputation: 3819

Ordering Items by Known Parent

Let's say I have a class called LinkedUser which looks something like this :

public class LinkedUser 
{
     public int Id {get; set;}         
     public int? ParentId {get; set;}
     public string CardNumber {get; set;}
     public int RootUserId {get; set;}
}

Now, let's say I want retrieve all LinkedUser's where RootUserId == 1, and I get back data that looks like this, in no particular order :

var linkedUserList = return new List<LinkedUser>()
{
    new LinkedUser {Id = 1, CardNumber = "546251357655", ParentId = null, RootUserId = 1},
    new LinkedUser {Id = 5869, CardNumber = "666547395503", ParentId = 1, RootUserId = 1},
    new LinkedUser {Id = 214, CardNumber = "666558432178", ParentId = 5869, RootUserId = 1},
    new LinkedUser {Id = 8957, CardNumber = "987265985430", ParentId = 214, RootUserId = 1},
    new LinkedUser {Id = 3650, CardNumber = "987653215430", ParentId = 8957, RootUserId = 1}
};

My Question :

What I would like to do is sort this list by descending ParentId's in terms of inheritance (not just the raw integer value).

I first solved this by adding an index property to the class, but I feel like this could be done way more elegantly through LINQ - I just can't wrap my head around the syntax to do it.

Can anyone help?

Upvotes: 0

Views: 55

Answers (2)

MethodMan
MethodMan

Reputation: 18843

public class LinkedUser
{
    public int Id { get; set; }
    public int? ParentId { get; set; }
    public string CardNumber { get; set; }
    public int RootUserId { get; set; }
}

var linkedUserList =  new List<LinkedUser>()
{
    new LinkedUser {Id = 1, CardNumber = "546251357655", ParentId = null, RootUserId = 1},
    new LinkedUser {Id = 5869, CardNumber = "666547395503", ParentId = 1, RootUserId = 1},
    new LinkedUser {Id = 214, CardNumber = "666558432178", ParentId = 5869, RootUserId = 1},
    new LinkedUser {Id = 8957, CardNumber = "987265985430", ParentId = 214, RootUserId = 1},
    new LinkedUser {Id = 3650, CardNumber = "987653215430", ParentId = 8957, RootUserId = 1}
};

List<LinkedUser> sortedList = linkedUserList.OrderBy(o => o.ParentId).ToList();

using the debugger to inspect linkedUserList you will see that from Items[0] thru item[4] the sortedList variable

item[0] ParentId = null

item[1] ParentId = 1

item[2] ParentId = 214

item[3] ParentId = 5869

item[4] ParentId = 8957

Upvotes: 0

Steve Cooper
Steve Cooper

Reputation: 21480

Would it be possible to build an actual tree?

var linkedUserList = return new List<LinkedUser>()
{
    new LinkedUser {Id = 1, CardNumber = "546251357655", ParentId = null, RootUserId = 1, Children = new [] {
        new LinkedUser {Id = 5869, CardNumber = "666547395503", ParentId = 1, RootUserId = 1, Children = new [] {
            new LinkedUser {Id = 214, CardNumber = "666558432178", ParentId = 5869, RootUserId = 1},
            ... etc
        }},

    }},
};

This puts you on a footing to manipulate each child collection individually.

So now you can walk the tree (uncompiled);

public void SortUser(LinkedUser user)
{
    user.Children.Sort((c1,c2) => Math.sign(c2-c1));
    foreach(var child in user.Children)
    {
        SortUser(child);
    }
}

Stick a 'Descendents' property on LinkedUser;

public IEnumrable<LinkedUser> Descendents()
{
    yield return this;
    foreach(var descendent in Children)
    {
        foreach(var result in child.Descendents())
        {
            yield return descendent;
        }
    }
}

Now you can do;

var hierarchicallyOrdered = linkedUserList.SelectMany(usr => usr.Descendents()).ToList();

Upvotes: 1

Related Questions