记录列表中的数字排名C#

时间:2013-08-11 11:50:51

标签: c# linq

问题: 我有一个列表编号(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) 谢谢!

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

但是,它有一个限制:它要求单个列表值是唯一的。