Count number of element in List>

前端 未结 4 1318
野性不改
野性不改 2021-02-12 07:53

I have a List>. How can I count all the elements in this as if it was a single List in the fastest way?

So far I h

相关标签:
4条回答
  • 2021-02-12 08:32

    I'd like to get the chance to answer this question just to highlight when we should use linq and when a classic for. Unfortunately today people doesn’t care a lot about performance as we got use to work on very powerful computer. Anyway just try the code below and you will discover that Linq is more then 100 times slower than the classic for version. You should use Linq only when the expression you need to write is really complex and you want make it more readable. I didn't spend time to the solution shoed below as I'd like to focus on the performance

    public static void Main(string [] arg)
    {
        //create the list
        List<List<string>> listOfList = new List<List<string>>()
                                          {
                                              new List<string>()
                                                  {
                                                      "1.1","2.2"
                                                  }
                                          ,
                                           new List<string>()
                                                  {
                                                      "2.1","2.2","2.3"
                                                  }
                                          };
        //stopwatch using Linq
        Stopwatch stopwatch=new Stopwatch();
        stopwatch.Start();
    
        int totalUsingLinq = listOfList.Sum(x => x.Count);
    
        stopwatch.Stop();
        Console.WriteLine("Using Linq:{0}",stopwatch.Elapsed); //00005713
    
        int totalUsingFor = 0;
        //stopwatch using classic for 
        stopwatch.Reset();
        stopwatch.Start();
        totalUsingFor = 0;
        for(int i=0;i<listOfList.Count;i++)
        {
           var mainItem = listOfList[i];
            if(mainItem!=null)
            {
                totalUsingFor += mainItem.Count;
            }
        }
        stopwatch.Stop();
        Console.WriteLine("Using for:{0}", stopwatch.Elapsed); //0000010
    
    }
    

    distinct version using for (just for example). In this case I have create a very "bottleneck" function that does the distinct and it is still faster.

     public class Program
        {
          public static void Main(string[] arg)
            {
                //create the list
                List<List<string>> listOfList = new List<List<string>>()
                                          {
                                              new List<string>()
                                                  {
                                                      "1.1","2.2","1.1","1.1","2.2","1.1","1.1","2.2","1.1","1.1"
                                                  }
                                          ,
                                           new List<string>()
                                                  {
                                                      "2.1","2.2","2.3","2.3","1.1","2.2","1.1","1.1","2.2","1.1","1.1","2.2","1.1","1.1","2.2","1.1","1.1","2.2","1.1"
                                                  }
                                          };
                //stopwatch using Linq
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();
    
                int totalUsingLinq = listOfList.Sum(l => l.Distinct().Count());
    
    
                stopwatch.Stop();
                Console.WriteLine("Using Linq:{0}", stopwatch.Elapsed); //000012150    
                int totalUsingFor = 0;
                //stopwatch using classic for 
                stopwatch.Reset();
                stopwatch.Start();
                totalUsingFor = 0;
                for (int i = 0; i < listOfList.Count; i++)
                {
                    var mainItem = listOfList[i];
                    if (mainItem != null)
                    {
                        for(int y=0;y<mainItem.Count;y++)
                        {
                          if(mainItem[y]!=null)
                          {
                              totalUsingFor++;
                              NullDuplicateItems(y, ref mainItem);
                          }   
                        }
                    }
                }
                stopwatch.Stop();
                Console.WriteLine("Using for:{0}", stopwatch.Elapsed); //0009440
            }
    
            public static void NullDuplicateItems(int index,ref List<string > list)
            {
                var item = list[index];
                for(int i=index+1;i<list.Count;i++)
                {
                    if(list[i]==item)
                    {
                        list[i] = null;
                    }
                }
            }
    
        }
    
    0 讨论(0)
  • 2021-02-12 08:36

    By using LINQ, I think your code is good with a bit changes that no need for .ToList(), just call Count() extension as the following:

    int result = listOfLists.SelectMany(list => list).Distinct().Count();
    
    0 讨论(0)
  • 2021-02-12 08:51

    I would recommend a simple, nested loop with a HashSet if you need to eliminate duplicates between lists. It combines the SelectMany and Distinct operations into the set insertion logic and should be faster since the HashSet has O(1) lookup time. Internally Distinct() may actually use something similar, but this omits the construction of the single list entirely.

    var set = new HashSet<T>();
    foreach (var list in listOfLists)
    {
        foreach (var item in list)
        {
            set.Add(item);
        }
    }
    var result = set.Count;
    
    0 讨论(0)
  • 2021-02-12 08:54

    To count all the elements in all the lists in the list, you could use the aggregating operators:

    int count = listOfLists.Sum(l => l.Distinct().Count());
    
    0 讨论(0)
提交回复
热议问题