我想对列表进行排序,并将地图从元素的旧位置保存到新位置?
例如,如果要排序的列表是
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]]);
答案 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