'Need help to sorting an array in a complicated way c# linq

I have a strict similar to this :

struct Chunk
 {
   public float d; // distance from player
   public bool active; // is it active
 }

I have an array of this struct.

What I need:

I need to sort it so the first element is an inactive chunk that is also the furthest from the player, than the next element is active and is also the closest to the player and that is the pattern,

  1. Inactive, furthest
  2. Active, closest
  3. Inactive, furthest
  4. Active, closest
  5. Inactive, furthest And so on...

Currently I'm using LINQ, And I'm doing this :

chunk = chunk.AsParallel().OrderBy(x => x.active ? x.d : -x.d).ToArray();

But I don't know how to make it alternate one after another.



Solution 1:[1]

It looks like you want to split this into two lists, sort them, then interleave them.

var inactive = chunk.Where(x => !x.active).OrderByDescending(x => x.d);
var active = chunk.Where(x => x.active).OrderBy(x => x.d);
var interleaved = inactive.Zip(active, (a, b) => new [] { a, b }).SelectMany(x => x);

Solution 2:[2]

Not sure if you can do it with only one line of code.

I wrote a method that would only require the Array to be sorted once. Then, it enters either the next closest or furthest chunk based on the current index of the for loop (odd = closest, even = furthest). I remove the item from the sorted list to ensure that it will not be reentered in the results list. Finally, I return the results as an Array.

public Chunk[] SortArray(List<Chunk> list_to_sort)
{
    //Setup Variables
    var results = new List<Chunk>();
    int count = list_to_sort.Count;

    //Tracking the sorting list so that we only need to sort the list once
    list_to_sort = list_to_sort.OrderBy(x => x.active).ThenBy(x => x.d).ToList();

    //Loop through the list
    for (int i = 0; i < count; i++)
    {
        results.Add(list_to_sort[i % 2 == 0 ? list_to_sort.Count - 1 : 0]);
        list_to_sort.RemoveAt(i % 2 == 0 ? list_to_sort.Count - 1 : 0);
    }

    // Return Results
    return results.ToArray();
}

There is probably a better way of doing this but hopefully it helps. Please note that I did not test this method.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Andrew Williamson
Solution 2