如何计算列表 A 中存在于列表 B 中的每个数字的出现次数,如果不存在,则 return 为零?
How to count the occurence of each number in list A that is exist in list B and return zero if not existed?
这是我在这个社区中的第一个问题,我想得到我的问题的答案,
假设我有两个列表 A 和 B:
List<int> listA = new List<int>();
List<int> listB = new List<int>();
listA.Add(1);
listA.Add(2);
listA.Add(8);
listB.Add(1);
listB.Add(1);
listB.Add(1);
listB.Add(2);
listB.Add(2);
listB.Add(2);
listB.Add(2);
我想计算 listB 中已存在于 listA 中的每个元素的出现次数,如果不存在则加零:
这是我试过的:
var result = listB.GroupBy(x => x).ToDictionary(k => k.Key, v => v.Count());
foreach(var res in result.Values)
Console.WriteLine(res); // it will print only {3,4}
预期结果将是:
// { 3,4,0} => 3 is the occurrences number of 1 , 4 is the occurrences number of 2 ,and 0 is the number occurrences of 8
我怎样才能达到这个结果?
在LINQ中使用left outer join是个好问题。这是一个article about it。这是最佳性能解决方案,因为您只需迭代一次集合,这对于大型集合或常用方法很重要。
这是您的问题的示例:
var result = from a in listA
join b in listB.GroupBy(x => x) on a equals b.Key into gj
from subList in gj.DefaultIfEmpty()
select new
{
Number = a,
Count = subList?.Count() ?? 0
};
您也可以使用 GroupJoin 和方法链接,但我认为它更难阅读:
var result = listA
.GroupJoin(listB.GroupBy(x => x), a => a, b => b.Key, (a, gj) => new { a, gj })
.SelectMany(@t => @t.gj.DefaultIfEmpty(), (@t, subList) => new { Number = @t.a, Count = subList?.Count() ?? 0 });
之后,结果将包含一个匿名类型的集合,其中包含字段 Number
和 Count
以及 3 个元素:{1, 3}, {2, 4}, {8, 0}
.
根据评论更新(感谢 Caius Jard):如果您不能使用 Null-Conditional Operator,您可以将其替换为显式检查:subList == null ? 0 : subList.Count()
我会使用 linq .Count() 扩展,它将计算满足条件的项目数。是的,这将比必要的次数更多地迭代列表,但它不会创建任何不必要的对象,而且它非常可读:
var countOccurences = new List<int>();
foreach (var inA in listA)
{
countOccurences.Add(listB.Count(inB => inB == inA));
}
Console.WriteLine(string.Join(", ", countOccurences));
一旦循环开始工作,那么应该很容易看出它可以在一条语句中完成:
var countOccurences = listA.Select(inA => listB.Count(inB => inA == inB));
修复您的代码
var result = listB.GroupBy(x => x).ToDictionary(k => k.Key, v => v.Count());
foreach(var ent in listA)
Console.WriteLine(result.ContainsKey(ent)?result[ent]:0);
一行 Linq 语句
listA.Select(a => listB.Contains(a) ? a : 0 ).Select(r=>listB.Count(w=> w==r)).ToList();
这是我在这个社区中的第一个问题,我想得到我的问题的答案, 假设我有两个列表 A 和 B:
List<int> listA = new List<int>();
List<int> listB = new List<int>();
listA.Add(1);
listA.Add(2);
listA.Add(8);
listB.Add(1);
listB.Add(1);
listB.Add(1);
listB.Add(2);
listB.Add(2);
listB.Add(2);
listB.Add(2);
我想计算 listB 中已存在于 listA 中的每个元素的出现次数,如果不存在则加零:
这是我试过的:
var result = listB.GroupBy(x => x).ToDictionary(k => k.Key, v => v.Count());
foreach(var res in result.Values)
Console.WriteLine(res); // it will print only {3,4}
预期结果将是:
// { 3,4,0} => 3 is the occurrences number of 1 , 4 is the occurrences number of 2 ,and 0 is the number occurrences of 8
我怎样才能达到这个结果?
在LINQ中使用left outer join是个好问题。这是一个article about it。这是最佳性能解决方案,因为您只需迭代一次集合,这对于大型集合或常用方法很重要。
这是您的问题的示例:
var result = from a in listA
join b in listB.GroupBy(x => x) on a equals b.Key into gj
from subList in gj.DefaultIfEmpty()
select new
{
Number = a,
Count = subList?.Count() ?? 0
};
您也可以使用 GroupJoin 和方法链接,但我认为它更难阅读:
var result = listA
.GroupJoin(listB.GroupBy(x => x), a => a, b => b.Key, (a, gj) => new { a, gj })
.SelectMany(@t => @t.gj.DefaultIfEmpty(), (@t, subList) => new { Number = @t.a, Count = subList?.Count() ?? 0 });
之后,结果将包含一个匿名类型的集合,其中包含字段 Number
和 Count
以及 3 个元素:{1, 3}, {2, 4}, {8, 0}
.
根据评论更新(感谢 Caius Jard):如果您不能使用 Null-Conditional Operator,您可以将其替换为显式检查:subList == null ? 0 : subList.Count()
我会使用 linq .Count() 扩展,它将计算满足条件的项目数。是的,这将比必要的次数更多地迭代列表,但它不会创建任何不必要的对象,而且它非常可读:
var countOccurences = new List<int>();
foreach (var inA in listA)
{
countOccurences.Add(listB.Count(inB => inB == inA));
}
Console.WriteLine(string.Join(", ", countOccurences));
一旦循环开始工作,那么应该很容易看出它可以在一条语句中完成:
var countOccurences = listA.Select(inA => listB.Count(inB => inA == inB));
修复您的代码
var result = listB.GroupBy(x => x).ToDictionary(k => k.Key, v => v.Count());
foreach(var ent in listA)
Console.WriteLine(result.ContainsKey(ent)?result[ent]:0);
一行 Linq 语句
listA.Select(a => listB.Contains(a) ? a : 0 ).Select(r=>listB.Count(w=> w==r)).ToList();