我有一个按照考试分数排序的列表,我想要获取这个列表中前N个元素。
如果第N个和第N+1个学生的考试分数相同,则列表必须包含它们两个。
例如,我有一个像这样的列表:
john. 80
mike. 75
james. 70
ashley. 70
kate. 60
前三名应该返回john、mike、james、ashley
我尝试了Take(),但它只返回john、mike、james
英语不是我的主要语言,如果我没有说清楚,抱歉
谢谢
这是一个仅需要单次遍历的实现:
public static IEnumerable<TSource> TopWithTies<TSource, TValue>(
this IEnumerable<TSource> source,
int count,
Func<TSource, TValue> selector)
{
if (source == null) throw new ArgumentNullException("source");
if (selector == null) throw new ArgumentNullException("selector");
if (count < 0) throw new ArgumentOutOfRangeException("count");
if (count == 0) yield break;
using(var iter = source.OrderByDescending(selector).GetEnumerator())
{
if(iter.MoveNext())
{
yield return iter.Current;
while (--count >= 0)
{
if(!iter.MoveNext()) yield break;
yield return iter.Current;
}
var lastVal = selector(iter.Current);
var eq = EqualityComparer<TValue>.Default;
while(iter.MoveNext() && eq.Equals(lastVal, selector(iter.Current)))
{
yield return iter.Current;
}
}
}
}
使用示例:
var data = new[]
{
new { name = "john", value = 80 },
new { name = "mike", value = 75 },
new { name = "james", value = 70 },
new { name = "ashley", value = 70 },
new { name = "kate", value = 60 }
};
var top = data.TopWithTies(3, x => x.value).ToList();
foreach(var row in top)
{
Console.WriteLine("{0}: {1}", row.name, row.value);
}
OrderByDescending
本身会执行 n*Log(n)
的排序。 - CharliefaceOrderByDescending
+ Take
+ SelectMany
:var topThreePoints = users.GroupBy(u => u.Points)
.OrderByDescending(g => g.Key)
.Take(3)
.SelectMany(g => g);
SelectMany()
从前3个组中进行投影,那么结果肯定会包括这200个项目以及其他两个组中的项目,对吧? - Frédéric Hamidivar nth = users.Skip(n-1).FirstOrDefault()
var top = users.TakeWhile(user => user.Score >= nth.Score)
可能是这样吗?
list.TakeWhile((item, index) => index < N || list[index] == list[index + 1]);
list[list.Length]
。我认为list[index] == list[index - 1]
没有这个问题,因为当index
为0时,index < N
成立。 - Lumen我在LINQPad中创建了一个示例案例。
var a = new List<Tuple<string,int>>();
a.Add(new Tuple<string,int>("john",80));
a.Add(new Tuple<string,int>("mike",75));
a.Add(new Tuple<string,int>("james",70));
a.Add(new Tuple<string,int>("ashley",70 ));
a.Add(new Tuple<string,int>("kate",60 ));
a.Where(x=>x.Item2>=a.OrderBy(i=>i.Item2).Skip(2).Take(1).SingleOrDefault ().Item2).Dump();
虽然不知道它是否足够高效。
WITH TIES
,是吗? - Marc GravellTake(n)
不考虑平局解决方法。 - Marco