问题:
我有一个列表编号(List<List<int>> listNumberCollection)
列表:4行x 3列
1 3 9
6 5 6
3 2 7
2 7 2
如何在列中记录等级(最小数字是第1个),因此它应该是:
1 2 4
4 3 2
3 1 3
2 4 1
我的工作: 为了对列中的数字进行排序,我编写了一个用于转置的函数(4列x 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的类,其中包含2个属性(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) 谢谢!
答案 0 :(得分:1)
使用纯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();
答案 1 :(得分:0)
我会跟随以下内容:
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
但是,它有一个限制:它要求单个列表值是唯一的。