如何对列表进行排序,将地图从旧位置保存到新位置?

时间:2014-02-24 13:41:30

标签: c# .net algorithm linq

我想对列表进行排序,并将地图从元素的旧位置保存到新位置?

例如,如果要排序的列表是

var words = "once upon a midnight dreary".Split();
// once upon a midnight dreary

然后排序的列表将是

var orderedWords = words.OrderBy(w => w).ToArray();
// a dreary midnight once upon

然后因为'一次'从位置0移动到位置3,地图将是

0 => 3, 1 => 4, 2 => 0, 3 => 2, 4 => 1

所以,对于所有我

words[i] = orderedWords[map[i]]

我该怎么做?我希望它能够在与普通排序相同的时间内完成,即。 O(n log n)


我试过了:

var map = words.Select((word, index) => new { Word = word, Index = index}).OrderBy(x => x.Word).Select(x => x.Index);

但是这给了

> 2, 4, 3, 0, 1

我的上述身份失败

for(int i = 0; i < words.Length; i++)
    Assert.AreEqual(words[i], orderedWords[map[i]]);

1 个答案:

答案 0 :(得分:3)

您必须在OrderBy之后使用新索引:

var map = words
    .Select((word, index) => new { Word = word, Index = index })
    .OrderBy(x => x.Word)
    .Select((x, NewIndex) => new { x.Word, x.Index, NewIndex });

结果:

[0] { Word = "a", Index = 2, NewIndex = 0 } 
[1] { Word = "dreary", Index = 4, NewIndex = 1 }    
[2] { Word = "midnight", Index = 3, NewIndex = 2 }
[3] { Word = "once", Index = 0, NewIndex = 3 }  
[4] { Word = "upon", Index = 1, NewIndex = 4 }  

更新:acc。评论:“如何将'旧索引到新索引'的数据结构输出?”

您可以使用词典:

var map = words
    .Select((word, index) => new { Word = word, OldIndex = index })
    .OrderBy(x => x.Word)
    .Select((x, NewIndex) => new { x.Word, x.OldIndex, NewIndex })
    .ToDictionary(x => x.OldIndex, x => x.NewIndex);

for (int i = 0; i < words.Length; i++)
{
     Console.WriteLine("Word: {0} \tOldIndex: {1} \tNewIndex: {2}", words[i], i, map[i]);
}

结果:

Word: once      OldIndex: 0     NewIndex: 3
Word: upon      OldIndex: 1     NewIndex: 4
Word: a         OldIndex: 2     NewIndex: 0
Word: midnight  OldIndex: 3     NewIndex: 2
Word: dreary    OldIndex: 4     NewIndex: 1