解决我的LIST中的职位排名?

Ste*_*anE 4 .net c# linq list

考虑以下代码:

class Results
{
    public int playerId;
    public int score;
    public int section;
    public int position;
    public Results(int _playerId, int _score, int _section)
    {
        playerId = _playerId;
        score = _score;
        section = _section;
    }
}

public void RankMyResults()
{
    List<Results> myResultList = new List<Results>();

    myResultList.Add(new Results(1,232, 1));
    myResultList.Add(new Results(2,213, 1));
    // Add a lot of more results

    // Iteriate over the items to set the position
}
Run Code Online (Sandbox Code Playgroud)

我想将位置1设置为每个部分中的最高分,将位置2设置为第二个最高分,依此类推.

此外,如果两个人的得分相同,那么这些职位应该是这样的

Position  Score   PlayerId Section
1         135     23       1
1         135     43       1
3         131     45       1
Run Code Online (Sandbox Code Playgroud)

如在此示例中,它将跳过位置2.

有没有一种很好的方法可以使用LINQ来执行此操作,或者使用List对象中的一些Select,Sorting功能?

我自己的解决方案迭代列表并不是很好!

Tho*_*que 8

几天前我写了这些扩展方法:

    #region RankBy

    public static IEnumerable<TResult> RankBy<TSource, TKey, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        Func<TSource, int, TResult> resultSelector)
    {
        return source.RankBy(keySelector, null, false, resultSelector);
    }

    public static IEnumerable<TResult> RankBy<TSource, TKey, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        IComparer<TKey> comparer,
        Func<TSource, int, TResult> resultSelector)
    {
        return source.RankBy(keySelector, comparer, false, resultSelector);
    }

    public static IEnumerable<TResult> RankByDescending<TSource, TKey, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        IComparer<TKey> comparer,
        Func<TSource, int, TResult> resultSelector)
    {
        return source.RankBy(keySelector, comparer, true, resultSelector);
    }

    public static IEnumerable<TResult> RankByDescending<TSource, TKey, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        Func<TSource, int, TResult> resultSelector)
    {
        return source.RankBy(keySelector, null, true, resultSelector);
    }

    private static IEnumerable<TResult> RankBy<TSource, TKey, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        IComparer<TKey> comparer,
        bool descending,
        Func<TSource, int, TResult> resultSelector)
    {
        comparer = comparer ?? Comparer<TKey>.Default;

        var grouped = source.GroupBy(keySelector);
        var ordered =
            descending
                ? grouped.OrderByDescending(g => g.Key, comparer)
                : grouped.OrderBy(g => g.Key, comparer);

        int totalRank = 1;
        foreach (var group in ordered)
        {
            int rank = totalRank;
            foreach (var item in group)
            {
                yield return resultSelector(item, rank);
                totalRank++;
            }
        }
    }

    #endregion

    #region DenseRankBy

    public static IEnumerable<TResult> DenseRankBy<TSource, TKey, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        Func<TSource, int, TResult> resultSelector)
    {
        return source.DenseRankBy(keySelector, null, false, resultSelector);
    }

    public static IEnumerable<TResult> DenseRankBy<TSource, TKey, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        IComparer<TKey> comparer,
        Func<TSource, int, TResult> resultSelector)
    {
        return source.DenseRankBy(keySelector, comparer, false, resultSelector);
    }

    public static IEnumerable<TResult> DenseRankByDescending<TSource, TKey, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        IComparer<TKey> comparer,
        Func<TSource, int, TResult> resultSelector)
    {
        return source.DenseRankBy(keySelector, comparer, true, resultSelector);
    }

    public static IEnumerable<TResult> DenseRankByDescending<TSource, TKey, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        Func<TSource, int, TResult> resultSelector)
    {
        return source.DenseRankBy(keySelector, null, true, resultSelector);
    }

    private static IEnumerable<TResult> DenseRankBy<TSource, TKey, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        IComparer<TKey> comparer,
        bool descending,
        Func<TSource, int, TResult> resultSelector)
    {
        comparer = comparer ?? Comparer<TKey>.Default;

        var grouped = source.GroupBy(keySelector);
        var ordered =
            descending
                ? grouped.OrderByDescending(g => g.Key, comparer)
                : grouped.OrderBy(g => g.Key, comparer);

        int rank = 1;
        foreach (var group in ordered)
        {
            foreach (var item in group)
            {
                yield return resultSelector(item, rank);
            }
            rank++;
        }
    }

    #endregion
Run Code Online (Sandbox Code Playgroud)

您可以按如下方式使用它们:

var rankedPlayers = players.RankByDescending(
                                p => p.Score,
                                (p, r) => new { Rank = r, Player = p });
Run Code Online (Sandbox Code Playgroud)

RankBy和之间的差异DenseRankByRankBy产生"间隙"(例如1,1,3,3,3,6 ......)而DenseRankBy不是(1,1,2,2,2,3 ...)