0

I am currently working on a simulation system so i've an array like

int[] arr = {2,5,9,10,0, 4,1,5,3};

I want array of indexes of values based on lower and output result like

result = {4, 6, 0, 8, 1, 7, 2, 3};

I searched all over for almost 3 days i can't find.

  • Can you explain exactly how you want the results to be sorted? – stuartd Jul 30 '22 at 12:24
  • Not sorted i just want the indexes based on lowest values eg in the above result array you can see, 4 is index of 0, 6 is index of 1, 0 is index of 2, 8 is index of 3 and etc. – Muhammad Baba Goni Jul 30 '22 at 12:34

2 Answers2

2

In the 2nd array you want the indexes of the elements in the first array as sorted in ascending order.

You can use LINQ to do this

int[] arr = { 2, 5, 9, 10, 0, 4, 1, 5, 3 };
int[] result = arr.Select((x, i) => (x, i))
    .OrderBy(t => t.x)
    .Select(t => t.i)
    .ToArray();

Here, we used an overload of Select that yields the index: Select<TSource,TResult>(IEnumerable, Func<TSource,Int32,TResult>).

The first Select creates a ValueTuple.

The test

Console.WriteLine(String.Join(", ", result));

Yields the result:

4, 6, 0, 8, 5, 1, 7, 2, 3

Note that the number 5 appears twice in the input array. Therefore, the result is ambiguous. (Your expected result has only 8 indexes but the input array has a length of 9)


My full .NET 6.0 test code (Console App):

namespace CoreConsoleApp;

internal static class SortedArrayIndexes
{
    public static void Test()
    {
        //  Indexes   0  1  2   3  4  5  6  7  8
        int[] arr = { 2, 5, 9, 10, 0, 4, 1, 5, 3 };
        int[] result = arr.Select((x, i) => (x, i))
            .OrderBy(t => t.x)
            .Select(t => t.i)
            .ToArray();
        Console.WriteLine(String.Join(", ", result));
    }
}

It is called in my Main method with:

SortedArrayIndexes.Test();
Console.ReadKey();

In case you are working with an older Framework or language version, you can also use the older System.Tuple Class

int[] result = arr.Select((x, i) => new Tuple<int, int>(x, i))
    .OrderBy(t => t.Item1)
    .Select(t => t.Item2)
    .ToArray();
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • Thank you very much. Let me try it. As for duplicate i want it to be on five come first serve. That's get the first 5 index before the latter. – Muhammad Baba Goni Jul 30 '22 at 12:48
  • The documentation of [Enumerable.OrderBy Method](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.orderby?view=net-6.0) says in the remarks section: *"This method performs a stable sort; that is, if the keys of two elements are equal, the order of the elements is preserved."*. Therefore, *"first come first serve"* is guaranteed. – Olivier Jacot-Descombes Jul 30 '22 at 12:53
  • It's given an error on `arr.Select((x, i) => (x, i))` a local variable x cannot be declared in this scope Another error in last `) expected` – Muhammad Baba Goni Jul 30 '22 at 13:07
  • I don't know your full code, but you might have declared another variable `x` somewhere. Then replace `x` by something else (e.g. with `v` for value`). Also if you are using an older version of C# (<= 6.0), the ValueTuples will not work. Click on the [ValueTuple](https://www.tutorialsteacher.com/csharp/valuetuple) link for more info. I added my full .NET 6.0 test code which is working. – Olivier Jacot-Descombes Jul 30 '22 at 13:20
  • Oh yes, mine is .NET 4.6 – Muhammad Baba Goni Jul 30 '22 at 13:29
  • You can sill add the [System.ValueTuple package](https://www.tutorialsteacher.com/csharp/valuetuple) as explained in the link and in case you are working with an older language version you can add [latest](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/configure-language-version) in the project file as explained in the link. Or use the old `System.Tuple` as explained in [What's the difference between System.ValueTuple and System.Tuple?](https://stackoverflow.com/questions/41084411/whats-the-difference-between-system-valuetuple-and-system-tuple). – Olivier Jacot-Descombes Jul 30 '22 at 13:37
0

We can use the built-in Array.Sort() method. It has a second parameter that returns the sorted indices as well, but it requires us to make a new array with the indices (i.e. starts from 0 and ends at the length of the original array)

int[] arr = {2,5,9,10,0,4,1,5,3};
int[] indexArr = Enumerable.Range(0, arr.Length).ToArray();
Array.Sort(arr, indexArr);

Note that you will need to add using System.Linq; if you get an error that Enumerable doesn't exist.

Moaaz Assali
  • 147
  • 1
  • 8