如何使用LINQ从列表中获取索引

时间:2014-05-22 16:38:10

标签: c# asp.net-mvc linq entity-framework

我有一个列表,我正在填写团队的总销售额。

lstTeamSales.OrderBy(x => x.TotalSales);

此列表包含int userIDdecimal totalSales

我按totalSales订购。那时我怎样才能确定登录人的等级?

我知道我可以将用户ID登录的人与列表中的userID进行比较。如果他在销售中排名第3,我需要返回他的等级的int,这将是Rank 3。

4 个答案:

答案 0 :(得分:2)

这个问题可以改为"我如何获得IEnumerable中的元素索引"。这是答案:How to get index using LINQ? 以下是如何使用它:

int rank = lstTeamSales.OrderBy(x => x.TotalSales).FindIndex(x => x.userID == currentUserID);

这比基于Select的方法稍微有效。

更新

  

看起来LINQ不支持.FindIndex。知道如何实现该功能吗?

     

我现在可能已经想到了它。我刚刚在ORderBy()之后添加了.ToList()。

无无无无!它杀死了整个想法:(想法是将extension method FindIndex添加到IEnumerable。然后使用它。参见示例:

static class FindIndexEnumerableExtension
{
    public static int FindIndex<T>(this IEnumerable<T> items, Func<T, bool> predicate)
    {
        if (items == null) throw new ArgumentNullException("items");
        if (predicate == null) throw new ArgumentNullException("predicate");

        int retVal = 0;
        foreach (var item in items)
        {
            if (predicate(item)) return retVal;
            retVal++;
        }
        return -1;
    }
}

class YourClass
{
    void YourMethod()
    {
        lstTeamSales.OrderBy(x => x.TotalSales).FindIndex(x => x.UserID == currentUserID);
    }
}

使用FindIndexEnumerableExtension扩展方法定义类FindIndex后,您可以在代码中的任何位置使用此方法。您只需要在模块中添加using指令,其中FindIndexEnumerableExtension已定义。这基本上就是LINQ的工作原理。

如果您不想使用此解决方案,那么至少在排序之前将lstTeamSales转换为List。并使用List<>.Sort()方法对其进行排序。

答案 1 :(得分:1)

您可以使用带有Func<TSource, Int32, TResult>(或等效表达式)的select扩展,如下所示:

var userId = /* the userId */;
lstTeamSales.OrderBy(x => x.TotalSales).Select((x, i) => new 
{
    x.UserId,
    x.TotalSales,
    Rank = i + 1
}).FirstOrDefault(x => x.UserId == theUserId);

这将返回一个对象,其中包含用户ID,总销售额和修复用户ID的排名。如果集合中没有null的实体,它将返回UserId = theUserId

索引(示例中的i)基于0。根据需要进行调整。

答案 2 :(得分:1)

根据总销售额列表lstTeamSales以及代表您希望找到userSales排名的销售数字,您需要的是{{1}的总销售数量超过lstTeamSales。如果它是你想要的等级,那么你可能想要排除等级中的关系(即如果前两个销售数字都是1000,那么它们都被排名为1)

您可以通过仅使用userSales投放销售数字,删除与Select电话的关联,然后使用Distinct来执行此操作:

Count

这将为您提供高于当前用户的总销售数量。从那里,当前用户的排名高于该数字:

lstTeamSales.Select(x => x.TotalSales).Distinct().Count(x => x > userSales)

答案 3 :(得分:0)

Select((item, index) => ...)表单允许这样做(如Simon所示),但是DMac提及您可能需要考虑重复。要将其合并到Select,您可以使用GroupBy

lstTeamSales
    .OrderByDescending(x => x.TotalSales).GroupBy(x => x.TotalSales)
    .Select((group, i) => new {
        Rank = i + 1,
        Users = group.Select(x => x.UserId)
    })

这将为您提供排名列表以及具有该排名的用户列表。或者您可以使用SelectMany将其展平,以获得每个用户的排名:

lstTeamSales
    .OrderByDescending(x => x.TotalSales).GroupBy(x => x.TotalSales)
    .SelectMany((x, i) => new {
        Rank = i + 1,
        User = x.UserId
    })

您可以过滤此序列以查找用户,但如果您只想查找特定用户的排名,那么DMac的解决方案是最直接的。例如,如果您想列出前5名卖家(请参阅Take),上述内容会更有用。