0

While working on my project I've encountered a little glitch in the way that List works.

I have this list for example:

# Username - Status - Order - Timestamp
Admin, Available (int 0), 2, 10:45
User1, Not available (int 2), 1, 10:44
User2, Available, 3, 10:52
User3, Busy (int 1), 4, 10:33

I want a way to order it by multiple properties using something like a comparer.

I would like it to order by Status, so Available comes first, then by Timestamp to know who was first in the list.

So it would output:

Admin, 0, 0, 10:45
User2, 0, 1, 10:52
User3, 1, 2, 10:33
User1, 2, -1, 10:44

The User1 order must become -1 because it is not available so I want it to show last in my list, as busy users comes just before.

I need to keep an order because I want to know who's next. I tried to iterate the old list with ordering it then creating a new one with the good order but it doesn't work.

Here's the method I use:

public static List<ListMember> ReOrder(this List<ListMember> list)
{
    int Index = 0;

    List<ListMember> newList = new List<ListMember>();
    foreach (ListMember member in list.OrderBy(x => x.ListOrder).ThenBy(x => x.DateEntered))
    {
        if (member.DateExited == null)
        {
            member.ListOrder = Index;

            Index++;
        }
        else
        {
            member.ListOrder = -1;
        }

        newList.Add(member);
    }

    return newList;
}

This is needed because when someone pass from status 1 to 0, he become available but I don't want him to go first, I want him to go last in the list, then reindex the list.

Does someone have an idea on how a list can be greatly ordered.

Frederick Marcoux
  • 2,195
  • 1
  • 26
  • 57
  • 3
    Possible duplicate of [Order a List (C#) by many fields?](http://stackoverflow.com/questions/2779375/order-a-list-c-by-many-fields) – Sinatr Nov 04 '15 at 15:53
  • You say you tried something already? Show what you did. – Ric Nov 04 '15 at 15:54
  • Consider to use [`Queue`](https://msdn.microsoft.com/en-us/library/7977ey2c.aspx) instead of `List` when you need queue. – Sinatr Nov 04 '15 at 15:54
  • 1
    Are you sure about the output ? User 1 is not available on your example. I would expect User2 before – carndacier Nov 04 '15 at 15:58
  • @Sinatr its not what he wants. (probably) because if you look at input and output properties are exchanged between items. so if provided output is not wrong then this is not a dupe. – M.kazem Akhgary Nov 04 '15 at 16:04
  • 2
    @M.kazemAkhgary, note that the order #s are also changed from Admin having 2 and User2 having 0 to suddenly Admin having 0 and User2 having -1 that would either suggest some processing being done somewhere, a typo or some other explanation here. – JB King Nov 04 '15 at 16:10
  • 1
    I think you should review your output or provide a better description of what you want . Why User2 order becomes "-1" ? Why is it in this order ? (User1 before User2) – carndacier Nov 04 '15 at 16:11
  • Edited question for better clarity. – Frederick Marcoux Nov 04 '15 at 16:33

2 Answers2

2

The Sinatr's comment should work.

As far as you need only available items, you can also do :

myList.Where(x => x.Status == 0).OrderBy(y => y.Timestamp)

I'm guessing to do the "Where" first will return a shorter list, then the orderBy would be faster to execute (someone to confirm ?)

Edit

After your edit, I would suggest to do like that :

public static List<ListMember> ReOrder(this List<ListMember> list)
{
    int Index = 0;

    foreach (ListMember member in list.OrderBy(x => x.DateEntered))
    {
        if (member.DateExited == null)
        {
            member.ListOrder = Index;

            Index++;
        }
        else
        {
            member.ListOrder = -1;
        }
    }

    return list;
}

I think you don't need to create a new list just to update a field. just update it directly in your list.

I would also suggest you to don't call often this function, because if you get a lot of items in your list, it can take time ! You should create a function in your ListMember Class, "SetDateExit". It could be :

public void SetDateExit(DateTime dateExit)
{
    this.DateExited = dateExit;
    this.ListOrder = -1;
}

And then, when you need to display your result, just do like that :

return myList.Where(x => ListOrder != -1).OrderBy(x => x.ListOrder);
carndacier
  • 960
  • 15
  • 38
0

You can use dynamic LINQ for ordering by multiple fields. Using Linq.Dynamic, and the NuGet (https://www.nuget.org/packages/System.Linq.Dynamic.Library/) you can use comma separated values to order

myList.OrderBy("Availibility,Timestamp");
Saransh Kataria
  • 1,447
  • 12
  • 19