【问题标题】:Count occurrences of order dependent List<T> in List<List<T>>在 List<List<T>> 中计算顺序相关 List<T> 的出现次数
【发布时间】:2020-03-07 23:22:31
【问题描述】:

有一个类似的问题没有回答我的问题。 --> Count number of element in List>

我有一个包含子列表的列表:

List<string> sublist1 = new List<string>() { "a", "b" };
List<string> sublist2 = new List<string>() { "a", "b" };
List<string> sublist3 = new List<string>() { "a", "c" };

现在我想计算每个列表的出现次数。

a, b --> 2
a, c --> 1

我使用了来自 LINQ 的 distinct(),但我得到了输出:

a, b --> 1
a, b --> 1
a, c --> 1

我假设哈希码是不同的。 distinct() 是否有替代方法来查看列表值? 如果可能的话,我想在 LINQ 中解决这个问题。

编辑: 列表项的顺序必须相同!

【问题讨论】:

  • 看起来像是 GroupBy() 的工作
  • @MatthewWatson 我试过这个,但GroupBy() 也返回三个独特的元素。 ://
  • distinct 将删除 dups,因此对于计数,您需要使用 groupby+count
  • 您可能需要编写自己的比较器。在我脑海中的某个地方是 LINQ 根据它们的引用比较像 List&lt;T&gt; 这样的对象的想法。这就是为什么distinct() 仍然给你三个项目。
  • 我无法删除其他人的反对票。

标签: c# list linq count compare


【解决方案1】:

我想我会解决这个问题:

var equallists = list1.SequenceEqual(list2);

因此,我将不同的列表和列表与 SequenceEquals() 进行比较并计算它们。

欢迎提供更好的解决方案。 :)

【讨论】:

    【解决方案2】:

    要使用GroupBy() 来执行此操作,您需要一个合适的IEqualityComparer&lt;List&lt;string&gt;&gt; 来比较字符串列表。没有内置的实现,所以你必须自己动手:

    public sealed class StringListEqualityComparer : IEqualityComparer<List<string>>
    {
        public bool Equals(List<string> x, List<string> y)
        {
            if (ReferenceEquals(x, y))
                return true;
    
            if (x == null || y == null)
                return false;
    
            return x.SequenceEqual(y);
        }
    
        public int GetHashCode(List<string> strings)
        {
            int hash = 17;
    
            foreach (var s in strings)
            {
                unchecked
                {
                    hash = hash * 23 + s?.GetHashCode() ?? 0;
                }
            }
    
            return hash;
        }
    }
    

    一旦你得到它,你就可以将它与GroupBy() 一起使用,如下所示:

    public static void Main()
    {
        var sublist1 = new List<string>{ "a", "b" };
        var sublist2 = new List<string>{ "a", "b" };
        var sublist3 = new List<string>{ "a", "c" };
    
        var listOfLists = new List<List<string>> {sublist1, sublist2, sublist3};
    
        var groups = listOfLists.GroupBy(item => item, new StringListEqualityComparer());
    
        foreach (var group in groups)
        {
            Console.WriteLine($"Group: {string.Join(", ", group.Key)}, Count: {group.Count()}");
        }
    }
    

    【讨论】:

      【解决方案3】:
           public JsonResult CountList(){
              List<List<string>> d = new List<List<string>>(); //SuperList
                  d.Add(new List<string> { "a", "b" }); //List 1
                  d.Add(new List<string> { "a", "b" }); // List 2
                  d.Add(new List<string> { "a", "c" }); // List 3
                  d.Add(new List<string> { "a", "c", "z" }); //List 4
                  var listCount = from items in d
                                  group items by items.Aggregate((a,b)=>a+""+b) into groups
                                  select new { groups.Key, Count = groups.Count() };
              return new JsonResult(listCount);
           }
      

      这将在 Post Man 或 Advanced REST Client 中输出以下结果

      [{
      "key": "ab",
      "count": 2
      },
        {
      "key": "ac",
      "count": 1
      },
        {
      "key": "acz",
      "count": 1
      }],
      

      【讨论】:

      • 但我的列表可能包含数百个条目。那我这还能用吗?
      • 是的,它适用于数百个列表。你可以测试一下
      • 我的意思是每个列表中有数百个列表条目。
      • 是的,它适用于每个列表中的数百个列表项。我刚刚写了一个测试,它非常快。自己测试一下。
      【解决方案4】:

      我认为这会有所帮助

       var list = new List<List<string>>() { sublist1, sublist2, sublist3};
       var result = list.GroupBy(x => string.Join(",",x)).ToDictionary(x => x.Key.Split(',').ToList(), x => x.Count());
      

      【讨论】:

        【解决方案5】:

        你可以试试下面的代码:-

                    List<string> sublist1 = new List<string>() { "a", "b" };   
                    List<string> sublist2 = new List<string>() { "a", "b" };   
                    List<string> sublist3 = new List<string>() { "a", "c" };   
                    List<List<string>> listOfLists = new List<List<string>> { sublist1, sublist2, sublist3 };    
                    Dictionary<string, int> counterDictionary = new Dictionary<string, int>();                  
                        foreach (List<string> strList in listOfLists)       
                        {   
                            string concat = strList.Aggregate((s1, s2) => s1 + ", " + s2);   
                            if (!counterDictionary.ContainsKey(concat))   
                                counterDictionary.Add(concat, 1);   
                            else   
                                counterDictionary[concat] = counterDictionary[concat] + 1;   
                        }   
                        foreach (KeyValuePair<string, int> keyValue in counterDictionary)   
                        {   
                               Console.WriteLine(keyValue.Key + "=>" + keyValue.Value);   
                        }   
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-09
          • 2019-05-20
          • 1970-01-01
          相关资源
          最近更新 更多