1

I have a list of Teams. A team is defined in this way:

public class Team
{
    public int ID { get; set; }

    public string Name { get; set; }
}

After I query the database with db.Teams.ToList(), which returns a List<Team>, I need to push one of the teams of that list with the name "Total" to the end of the list. How can I achieve this?

João Paiva
  • 1,937
  • 3
  • 19
  • 41
  • what do you mean to the end? if you mean the next index, that's its default behavior – Yar Sep 17 '16 at 19:16
  • 1
    why can't you sort the list on the C# side or the DataBase side..? also you can remove the item and Insert it back into the list based on an Index.. also edit the question and show us exactly what the items look like in the current list.. – MethodMan Sep 17 '16 at 19:18
  • @Yar To the end of the list. I retrieve the list of teams from the database. If the team named "Total" is in the middle of that list, I want to sort it to the end of that list. – João Paiva Sep 17 '16 at 19:18
  • @MethodMan What do you mean? I have the Team class definition in my answer. It is a List. My problem is if I remove it from the list, how can I add it again if I no longer have access to it? – João Paiva Sep 17 '16 at 19:23
  • Are you saying like List myList = new List(); myList.Add(myList.RemoveAt(5))? – Shannon Holsinger Sep 17 '16 at 19:25

3 Answers3

3

First, you can do that directly in the query:

var list = db.Teams.OrderBy(t => t.Name == "Total" ? 1 : 0).ToList();

But if you insist doing it after the list is populated, then you can use the FindIndex method to find the index of the total item (if any) and them move the item to the end using RemoveAt and Add methods:

var list = db.Teams.ToList();
int index = list.FindIndex(t => t.Name == "Total");
if (index >= 0 && index != list.Count - 1)
{
    var total = list[index];
    list.RemoveAt(index);
    list.Add(total);
}

In the later case, if you don't really care about the order of the other items in the list, another more efficient way would be to simply exchange the total with the last element:

if (index >= 0 && index != list.Count - 1)
{
    var total = list[index];
    list[index] = list[list.Count - 1];
    list[list.Count - 1] = total;
}
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • I tried your LINQ expression but it didn't work. – João Paiva Sep 17 '16 at 19:32
  • I assume you want to show the team total in a `view` or pass it along to another service. Best pattern to follow would be to query the existing `List` and create a new object `Team` out of it; but to achieve the result based on the question - once the `List` is already populated, you can insert the new `Team` object with `Name = Total` and while rendering use a search on the `Name` property to render it last. Hope you understand what I meant. – L J Sep 17 '16 at 19:37
  • What do you mean it didn't work? Are you getting error or incorrect result? I'll be quite surprised because I was doing a lot of such queries w/o problem. – Ivan Stoev Sep 17 '16 at 19:40
  • In other words, do a lookup on `Team.Name != Total` in your first loop and after the looping is over, check in the list for `Team.Name == Total` - it doesn't matter where the `Team` is placed. It is up to how you use the query than to how you inject the object. – L J Sep 17 '16 at 19:42
  • @IvanStoev I tried it, but the Team with name "Total" didn't come in the end of the list. It still appeared in the middle. – João Paiva Sep 17 '16 at 19:42
  • @JoãoPaiva It's really hard to believe. Is the "Total" case correct in the database? Any spaces etc. Anyway, I do believe both parts of the answer are correct, there is nothing more I can suggest you. – Ivan Stoev Sep 17 '16 at 19:52
  • @IvanStoev I gave you correct answer for your double solution, but I still can't get the LINQ query to work. Do you think there might be something wrong with the expression, It would be really useful for me to use it. – João Paiva Sep 17 '16 at 20:12
  • You are welcome. There must be something else because the expression is quite simple. May be if you provide more info, like if you are using EF, what version (I'm testing on latest 6.1.3), database type, the generated SQL query etc. – Ivan Stoev Sep 17 '16 at 20:56
  • @IvanStoev For the sake of simplicity I said in my question that I was querying a List from db.Teams. However, I'm really querying a Contract from db.Contracts which has a property that is a List. I did some investigation and I think that EF doesn't allow the sorting of nested objects. Do you know anything about this? – João Paiva Sep 18 '16 at 12:58
  • Simplifying is good as soon as it doesn't miss important details, which seems to be the case. I would suggest you posting another question with realistic example. Everything matters - query structure, lazy/eager loading etc. – Ivan Stoev Sep 18 '16 at 15:20
1

Get the list and move the one you want to the last index. Note that you don't need to order the list. Say your object is 2 in this case:

List<int> list = new List<int>
{
    0,
    1,
    2,
    3,
    4
};

// get the object o(n)
int tmp = list.IndexOf(2);
// remove it
list.RemoveAt(2);
// add it to the end of list
list.Add(tmp);
Yar
  • 7,020
  • 11
  • 49
  • 69
1

Short answer: Generate hash-code

Please look at this answer from @Jon Skeet - https://stackoverflow.com/a/8094931/6830901

More simple based on the requirement as I understand:

Do a lookup on Team.Name != "Total" in your first loop and after the looping is over, check in the list for Team.Name == "Total"

It doesn't matter where the Team is placed (think about a shared list). It is up to how we use the query than to where we inject the object

Community
  • 1
  • 1
L J
  • 5,249
  • 3
  • 19
  • 29