使用LINQ排序后,获取集合中项目的新索引

Mar*_*ein 16 c# linq arrays sorting list

我想在C#中对列表(或数组)进行排序,并希望为未排序列表中的每个项目保存新索引.即:

A = 2 3 1

sorted(A) = 1 2 3

indexes = 1 2 0 <-- This is what I need
Run Code Online (Sandbox Code Playgroud)

我在Stack溢出上读到LINQ特别有用,但我找不到具体怎么做.

naw*_*fal 21

注意:

我犯了一个错误的误读OP的问题(并且因为收到了这么多的赞成而感到尴尬).我希望(理想情况下)OP接受其中一个答案是正确的.为了对胜利者和SO的精神伸张正义,我将修改这个答案以使其正确.


一个可以携带两个扩展方法,一个用于旧索引,一个用于新索引(这是OP想要的).

public static IEnumerable<int> OldIndicesIfSorted<T>(this IEnumerable<T> source) where T : IComparable<T>
{
    return source
        .Select((item, index) => new { item, index })
        .OrderBy(a => a.item)
        .Select(a => a.index);
}

public static IEnumerable<int> NewIndicesIfSorted<T>(this IEnumerable<T> source) where T : IComparable<T>
{
    return source
        .OldIndicesIfSorted()
        .Select((oldIndex, index) => new { oldIndex, index })
        .OrderBy(a => a.oldIndex)
        .Select(a => a.index);
}
Run Code Online (Sandbox Code Playgroud)

称之为,

//A = [2, 3, 1];
A.NewIndicesIfSorted(); // should print [1, 2, 0]
Run Code Online (Sandbox Code Playgroud)

这两种方法都很懒惰,但NewIndicesIfSorted理想情况下应根据Matthew Watson的答案编写,这种方法效率更高.我和Mat的答案的好处是可以很好地处理重复的条目.

  • @SonerGönül索引显示原始项目在排序数组中的位置.因此索引0处的原始项目(值为2)最终在索引1处.索引1处的原始项目(值为3)最终在索引2处.索引2处的原始项目(这是值1)最终在索引0处.因此:`1,2,0` (4认同)
  • 我_still_不明白`3`的索引应该是'0` oO (2认同)
  • 讽刺的方式是OrderBy通过生成一系列求助索引在内部工作,然后通过它们进行枚举.(一方面,交换两个索引比两个大值类型元素更便宜). (2认同)

小智 8

您可以使用LINQ选择执行此操作:

var a =new [] {2,3,1};

var sorted = a.OrderBy (x => x).ToList();
var indexes = a.Select (x => sorted.IndexOf(x));
Run Code Online (Sandbox Code Playgroud)

如果这是一个巨大的列表而不是这个简单的列表,它可能会有点低效,但确实会返回您期望的内容.