C#中的VBA / Excel RANK

我正在创build从电子表格到C#的计算,我想知道如果C#有一个类似的方法来在Excel排名?

在Excel中排名

返回数字列表中的数字的等级。 数字的排名是其大小相对于列表中的其他值。 (如果你要对这个列表进行sorting,这个数字的排名就是它的位置。)

句法

RANK(号码,参考文献,顺序)

数字是您想要查找的等级的数字。

Ref是一个数组列表,或者是一个数字列表的引用。 ref中的非数字值被忽略。

订单是一个数字,指定如何排名数字。

如果订单为0(零)或省略,Microsoft Excel排名数字就好像ref是一个按降序排列的列表。 如果订单是非零值,则Microsoft Excel将按照升序排列的列表sorting。

同样可以通过代码来实现,但我只是想检查是否有什么我先失踪。

你可以,有点。

SortedList<int, object> list = new SortedList<int, object>(); // fill with unique ints, and then look for one int rank = list.Keys.IndexOf(i); 

排名将是一个上升的,基于零的位置。

你可以通过编写一个扩展方法来实现它:

 public static class Extensions { public static int Rank(this int[] array, int find) { SortedList<int, object> list = new SortedList<int, object>(); for (int i = 0; i < array.Length; i++) { list.Add(array[i], null); } if (list.ContainsKey(find)) { return list.Keys.IndexOf(find); } else { return -1; } } } 

并使用它:

  int[] ints = new int[] { 2, 7, 6, 3, 9, 12 }; int rank = ints.Rank(2); 

…但我不相信它是最明智的做法。

要获得RANK的等价物,您需要获得每个物品的最小索引:

 var ranks = list.OrderBy(x => x) .Select((x, i) => new {x, i = i+1}) // get 1-based index of each item .GroupBy(xi => xi.x) // group by the item .Select(g => new {rank = g.Min(xi => xi.i), items = g}) // rank = min index of group .SelectMany(g => g.items, (g, gg) => new {g.rank, gg.i}) ; // select rank and item 

或者如果你按照课程的属性分组:

 var ranks = list.OrderBy(x => x.{some property}) .Select((x, i) => new {x, i = i+1}) // get 1-based index of each item .GroupBy(xi => xi.x.{some property}) // group by the item's property .Select(g => new {rank = g.Min(xi => xi.i), items = g}) // rank = min index of group .SelectMany(g => g.items, (g, gg) => new {g.rank, gg.i}) ; // select rank and item 

这对我来说目前为止(而且更简单)

 public static int Rank<T>(T value, IEnumerable<T> data) { return data.OrderByDescending(x => x).ToList().IndexOf(value) + 1; } 

我用T所以它可以采取所有的数字types( int / double / decimal )。

用法与Excel类似

 int[] data = new[] { 3, 2, 2, 3, 4 }; int rank = Rank(3, data); // returns 2 

我希望我没有错过任何东西