使用LINQ计算列表中项目的出现次数

时间:2014-02-12 16:09:10

标签: c# linq linq-to-sql

我正在尝试使用LINQ

计算列表中项目的出现次数

我有以下架构 -

用户(提供的所有条目),计数(待计算)

计数应该像 -

enter image description here

我想不出一个优雅的解决方案。

甚至只能使用LINQ吗?如果没有,我们如何使用LINQ和一些C#代码来实现这一点。

4 个答案:

答案 0 :(得分:3)

你可以通过循环和Enumerable.Take的组合来做到这一点,例如:

for (int i = 0; i < list.Count; i++)
{
    //Get count of current element to before:
    int count = list.Take(i+1)
                    .Count(r => r.UserName == list[i].UserName);
    list[i].Count = count;
}

list定义为:

List<User> list = new List<User>
    {
        new User{UserName = "A"},
        new User{UserName = "B"},
        new User{UserName = "A"},
        new User{UserName = "A"},
        new User{UserName = "B"},
        new User{UserName = "A"},
        new User{UserName = "C"},
        new User{UserName = "A"},

    };

User类为:

public class User
{
    public string UserName { get; set; }
    public int Count { get; set; }
}

稍后您可以打印输出,如:

foreach (var item in list)
{
    Console.WriteLine("UserName: {0}, Running Total: {1}", item.UserName, item.Count);
}

你会得到:

UserName: A, Running Total: 1
UserName: B, Running Total: 1
UserName: A, Running Total: 2
UserName: A, Running Total: 3
UserName: B, Running Total: 2
UserName: A, Running Total: 4
UserName: C, Running Total: 1
UserName: A, Running Total: 5

答案 1 :(得分:2)

可以用LINQ完成吗?可能不容易。可以用你自己的扩展方法很容易地完成吗?当然(我实际上并没有尝试编译和运行代码,所以我不能保证它会起作用,但它绝对是一个很好的起点):

public static IEnumerable<Tuple<T, int>> RunningTotal<T>(this IEnumerable<T> source)
{
    var counter = new Dictionary<T, int>();

    foreach(var s in source)
    {
        if(counter.ContainsKey(s))
        {
            counter[s]++;
        }
        else
        {
            counter.Add(s, 1);
        }

        yield return Tuple.Create(s, counter[s]);
    }
}

答案 2 :(得分:1)

你可以这样做没有双重迭代这样的集合: -

        var values = "ABAABCA".ToArray();

        var counts = new Dictionary<char, int>();

        var counter = values.Select(ch => 
            { 
                int count = counts[ch] = counts.ContainsKey(ch) ? counts[ch] + 1 : 1;
                return new {ch, count}; 
            });

        foreach (var c in counter)
            Console.WriteLine(c.ch + " -> " + c.count);

答案 3 :(得分:0)

我是通过使用Select来做到这一点的。我正在编写一个同步功能,它可以从魔兽世界API中获取项目,并且某些项目不再适用于API,即使它们在技术上仍然在游戏中。由于我按照拍卖行上市次数的顺序同步物品,因此会被这些物品卡住。

我创建了一个不良商品ID列表。如果该项目无法同步,我会将其添加到列表中。我想跳过该项目,如果它不能同步3次。我用以下代码完成了这个:

private int[] GetBadItemList()
{
    var ids = from i in _badItemIDs
              where _badItemIDs.Select(curItem => curItem.Equals(i)).Count() >= MAX_ITEM_TRYS
              select i;
    return ids.ToArray();
}