Reputation:
I have an array of values and I want to create a sorting index, i.e. an auxiliary array of integers that lists the element in sorted order by indirect addressing.
In other words,
I <= J -> Value[Index[I]] <= Value[Index[J]]
How can I define a comparator for the Sort
method to achieve that ? The array of values must remain unchanged.
Upvotes: 0
Views: 297
Reputation: 205629
The easiest way to build such an index I see is to use LINQ:
var Index = Enumerable.Range(0, Value.Length).OrderBy(i => Value[i]).ToArray();
or if you insist on using Array.Sort
, then you can use the overloads that accept Comparison<T>
delegate:
var Index = new int[Value.Length];
for (int i = 0; i < Index.Length; i++)
Index[i] = i;
Array.Sort(Index, (a, b) => Comparer<Value_Type>.Default.Compare(Value[a], Value[b]));
where the Value_Type
is the type of the Value
array elements.
Another option (IMO the best) is to create a reusable generic comparer like this:
public static class Comparers
{
public static IComparer<int> CreateIndexComparer<T>(this IReadOnlyList<T> source, IComparer<T> comparer = null)
{
return new ListIndexComparer<T>(source, comparer);
}
private sealed class ListIndexComparer<T> : Comparer<int>
{
readonly IReadOnlyList<T> list;
readonly IComparer<T> comparer;
public ListIndexComparer(IReadOnlyList<T> list, IComparer<T> comparer = null)
{
this.list = list;
this.comparer = comparer ?? Comparer<T>.Default;
}
public override int Compare(int x, int y)
{
return x != y ? comparer.Compare(list[x], list[y]) : 0;
}
}
}
and use it with the Array.Sort
overloads that accept IComparer<T>
:
Array.Sort(Index, Value.CreateIndexComparer());
Upvotes: 1