0

I have a strange question :)

I have a object list looking like this:

var list = new []
{
    new { Id = 1, Name = "Marcus" },
    new { Id = 2, Name = "Mattias" },
    new { Id = 3, Name = "Patric" },
    new { Id = 4, Name = "Theodor" },
};

I would like to sort the list providing a "start id"

For example, if I provide "start id" 3, the result should look like this:

Id Name
3 Patric
4 Theodor
1 Marcus
2 Mattias

I have no idea where to start, so I really need some help from you coding gods

The list is from a sql table, but it does not matter for me where the sort take place (in sql query or in c# code)

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
Marcus
  • 139
  • 1
  • 2
  • 9

5 Answers5

5

Try this:

var list = new []
{
    new { Id = 1, Name = "Marcus" },
    new { Id = 2, Name = "Mattias" },
    new { Id = 3, Name = "Patric" },
    new { Id = 4, Name = "Theodor" },
};

var start_id = 3;
var max_id = list.Max(y => y.Id);

var result =
    from x in list
    orderby (x.Id + max_id - start_id) % max_id
    select x;

I get:

result

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
3

With LINQ to objects you can do something like that:

var list = new []
{
    new { Id = 1, Name = "Marcus" },
    new { Id = 2, Name = "Mattias" },
    new { Id = 3, Name = "Patric" },
    new { Id = 4, Name = "Theodor" },
};
var startId = 3;

var result = list
    .GroupBy(i => i.Id >= startId ? 1 : 0) // split in two groups 
    .OrderByDescending(g => g.Key) // sort to have the group with startId first
    .Select(g => g.OrderBy(i => i.Id)) // sort each group
    .SelectMany(i => i) // combine result
    .ToList();

Console.WriteLine(string.Join(", ", result.Select(i => i.Id))); // prints "3, 4, 1, 2"
Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • `g.OrderBy(g => g.Id))` will throw up and error because you've already declared `g` in the `Select` so I suggest renaming it – Izzy May 27 '21 at 13:23
  • 1
    @Izzy actually it is not throwing in the latest .NET version. But still I should fix it. – Guru Stron May 27 '21 at 13:24
  • @Enigmativity falling over for me on .net 4.5 – Izzy May 27 '21 at 13:26
  • @Izzy I believe it is not related to .NET version, but language version, see [this](https://stackoverflow.com/a/59973360/2501279) and [this](https://github.com/dotnet/csharplang/blob/main/meetings/2019/LDM-2019-01-16.md) – Guru Stron May 27 '21 at 13:27
  • @GuruStron Thanks for that, I will have a read through it – Izzy May 27 '21 at 13:28
1

You require 2 criteria to apply:

  1. Order ascending by Id.
  2. Return the Ids greater than threshold before the Ids less than threshold.

You can try:

var offset = 3;
var sorted1 = list
    .OrderBy(item => item.Id < offset)
    .ThenBy(item => item.Id);

The OrderBy condition yields true if Id is less than offset and false otherwise. true is greater than false and therefore is returned later

A dirty way could also be:

var offset = 3;
var sorted2 = list
    .OrderBy(item => unchecked((uint)(item.Id - offset)));

Here the offset is subtracted from Id and the result converted to unsigned int to make the negative values become very large positive ones. A little hacky. Might not work with queries against SQL providers.

Rubidium 37
  • 661
  • 6
  • 12
0

Here's a toy Non-Linq Version

object[] ShiftList(int id)
{
    var list = new dynamic[]
    {
        new { Id = 1, Name = "Marcus" },
        new { Id = 2, Name = "Mattias" },
        new { Id = 3, Name = "Patric" },
        new { Id = 4, Name = "Theodor" },
    };

    Span<dynamic> listSpan = list;

    int indexFound = -1;

    for (int i = 0; i < list.Length; i++)
    {
        if (listSpan[i].Id == id)
        {
            indexFound = i;
        }
    }

    if (indexFound is -1)
    {
        return list;
    }

    var left = listSpan.Slice(0, indexFound);

    var right = listSpan[indexFound..];

    object[] objs = new object[list.Length];

    Span<object> objSpan = objs;

    right.CopyTo(objSpan);

    left.CopyTo(objSpan[right.Length..]);

    return objs;
}
DekuDesu
  • 2,224
  • 1
  • 5
  • 19
-2

Try using foreach and iterate over each object in your list:

            foreach (var item in list)
        {

        }

from here you should be able to use some of the collection methods for a list to reorder your list.

itz4blitz
  • 53
  • 7
  • Given that they tagged the question with LINQ, I’d assume they’re expecting any C# based solution to be in LINQ. – Jeremy Caney May 27 '21 at 17:43