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

我试图使用LINQ计算列表中项目的出现次数,

我有以下架构 –

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

伯爵应该像 –

在此处输入图像描述

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

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

你可以通过循环和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 list = new List { 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 

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

 public static IEnumerable> RunningTotal(this IEnumerable source) { var counter = new Dictionary(); foreach(var s in source) { if(counter.ContainsKey(s)) { counter[s]++; } else { counter.Add(s, 1); } yield return Tuple.Create(s, counter[s]); } } 

你可以这样做而不需要像这样重复迭代这套: –

  var values = "ABAABCA".ToArray(); var counts = new Dictionary(); 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); 

我通过使用Select来做到这一点。 我正在编写一个同步function,它可以从魔兽世界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(); }