问题:我有一个列表编号为(List<List<int>> listNumberCollection)
的列表:4行x 3列
1 3 9
6 5 6
3 2 7
2 7 2
我如何在列中记录排名(最小的数字是第一),所以它应该是:
1 2 4
4 3 2
3 1 3
2 4 1
我的工作:为了在一列中排序数字,我编写了一个换位函数(4列×3行):
1 6 3 2
3 5 2 7
9 6 7 2
private List<List<Double>> MatrixTransposition(int k, List<List<Double>> listNumberCollection)
{
var revisedAllRanks = new List<List<Double>>();
for (int i = 0; i < k; i++ )
{
var allRanks = new List<Double>();
allRanks.AddRange(listNumberCollection.Select(value => value[i]));
revisedAllRanks.Add(allRanks);
}
return revisedAllRanks;
}
我试图创建一个名为NumberRank的类,它有两个属性(Number,Rank),并添加到NumberRank列表中
var revisedListNumberCollection = MatrixTransposition(k, listNumberCollection);
var listNumberRanks = new List<List<NumberRank>>();
foreach(List<Double> vectorsCollection in revisedListNumberCollection)
{
List<NumberRank> numberRanks = vectorsCollection.OrderByDescending(number => number).Select((number, i) => new NumberRank(number, i + 1)).ToList();
listNumberRanks.Add(numberRanks);
}
然而,我得到的结果是有秩的有序数字(第一列:1-1 2-2 3-3 6-4…),而不是我想要的(1-1 6-4 3-3 2-2)谢谢
使用纯Linq 可以轻松完成
var input = new List<List<int>>() {
new List<int> { 1, 6, 3, 2 },
new List<int> { 3, 5, 2, 7 },
new List<int> { 9, 6, 7, 2 }
};
var result = input.Select(l =>
l.Select((x, i) => new { x = x, i = i}) // selecting index
.OrderBy(z => z.x) // sorting by value
.Select((z, j) => new { i = z.i, j = j + 1 }) // selecting rank
.OrderBy(z => z.i) // sorting by initial index
.Select(z => z.j) // returning rank
.ToList()
).ToList();
// List<List<int>>(3)
// {
// List<int>(4) { 1, 4, 3, 2 },
// List<int>(4) { 2, 3, 1, 4 },
// List<int>(4) { 4, 2, 3, 1 }
//}
更新要将行转换为列并返回,您可以执行以下操作:
var transp_input = Enumerable.Range(0, input[0].Count)
.Select(i => input.Select(x => x[i]));
然后你计算
var transp_result = transp_input.Select(l =>
l.Select((x, i) => new { x = x, i = i }) // selecting index
.OrderBy(z => z.x) // sorting by value
.Select((z, j) => new { i = z.i, j = j + 1 }) // selecting rank
.OrderBy(z => z.i) // sorting by initial index
.Select(z => z.j) // returning rank
.ToList()
).ToList();
并转置回
var result = Enumerable.Range(0, transp_result[0].Count)
.Select(i => transp_result.Select(x => x[i]).ToList()).ToList();
我会选择以下选项:
var input = new List<List<int>>() {
new List<int> { 1, 6, 3, 2 },
new List<int> { 3, 5, 2, 7 },
new List<int> { 9, 6, 7, 2 }
};
var results = new List<List<int>>(input.Count);
foreach (var list in input)
{
var rankDict = list.OrderBy(x => x).Select((v, i) => new { v, i }).ToDictionary(x => x.v, x => x.i);
results.Add(list.Select(x => rankDict[x] + 1).ToList());
}
foreach (var list in results)
{
Console.WriteLine(string.Join(" ", list.Select(x => x.ToString())));
}
这不是纯粹的LINQ,但做你所期望的。结果是:
1 4 3 2
2 3 1 4
4 2 3 1
但是,它有一个限制:它要求单个列表值是唯一的。