代码之家  ›  专栏  ›  技术社区  ›  Dotnet_Developer10

如何计算列表A中存在于列表B中的每个数字的出现次数,如果不存在则返回零?

  •  1
  • Dotnet_Developer10  · 技术社区  · 3 年前

    这是我在这个社区的第一个问题,我想得到我问题的答案, 假设我有两个列表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
    

    我怎样才能达到这个结果?

    3 回复  |  直到 3 年前
        1
  •  2
  •   John V    3 年前

    我会用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));
    
        2
  •  0
  •   pm100    3 年前

    修正你的代码

    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); 
    
        3
  •  0
  •   Vadim Martynov    3 年前

    在LINQ中使用左外连接是一个很好的问题。这里有一个 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} .

        4
  •  0
  •   Yasser S.    3 年前

    单线Linq站

    listA.Select(a => listB.Contains(a) ? a : 0 ).Select(r=>listB.Count(w=> w==r)).ToList();