Merge multiple Lists into one List with LINQ

前端 未结 8 1795
南方客
南方客 2020-11-28 12:50

Is there a slick way to merge multiple Lists into a single List using LINQ to effectively replicate this?

public class RGB
{
    public int Red { get; set; }         


        
8条回答
  •  日久生厌
    2020-11-28 13:14

    For what it's worth, I like LINQ and use it frequently, but sometimes the old-fashioned way is the best. Note these examples:

            const int Max = 100000;
            var rnd = new Random();
            var list1 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
            var list2 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
    
            DateTime start;
    
            start = DateTime.Now;
            var r1 = list1.Zip(list2, (a, b) => new { a, b }).ToList();
            var time1 = DateTime.Now - start;
    
            start = DateTime.Now;
            var r2 = list1.Select((l1, i) => new { a = l1, b = list2[i]}).ToList();
            var time2 = DateTime.Now - start;
    
            start = DateTime.Now;
            var r3 = new int[0].Select(i => new { a = 0, b = 0 }).ToList();
            //  Easy out-of-bounds prevention not offered in solution #2 (if list2 has fewer items)
            int max = Math.Max(list1.Count, list2.Count);
            for (int i = 0; i < max; i++)
                r3.Add(new { a = list1[i], b = list2[i] });
            var time3 = DateTime.Now - start;
    
            Debug.WriteLine("r1 == r2: {0}", r1.SequenceEqual(r2));
            Debug.WriteLine("r1 == r3: {0}", r1.SequenceEqual(r3));
            Debug.WriteLine("time1 {0}", time1);
            Debug.WriteLine("time2 {0}", time2);
            Debug.WriteLine("time3 {0}", time3);
    

    The output is:

    r1 == r2: True
    r1 == r3: True
    time1 00:00:00.0100071
    time2 00:00:00.0170138
    time3 00:00:00.0040028

    Of course, the time is barely noticeable in this case (to human perception) so it comes down to preference, but knowing #3 is by far the fastest, I'd tend to use it in critical performance areas where the types were more complex or the enumerables could be large.

    Also, note the difference when using 3:

            const int Max = 100000;
            var rnd = new Random();
            var list1 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
            var list2 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
            var list3 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
    
            DateTime start;
    
            start = DateTime.Now;
            var r1 = list1.Zip(list2, (a, b) => new { a, b }).Zip(list3, (ab, c) => new { ab.a, ab.b, c }).ToList();
            var time1 = DateTime.Now - start;
    
            start = DateTime.Now;
            var r2 = list1.Select((l1, i) => new { a = l1, b = list2[i], c = list3[i] }).ToList();
            var time2 = DateTime.Now - start;
    
            start = DateTime.Now;
            var r3 = new int[0].Select(i => new { a = 0, b = 0, c = 0 }).ToList();
            //  Easy out-of-bounds prevention not offered in solution #2 (if list2 or list3 have fewer items)
            int max = new int[] { list1.Count, list2.Count, list3.Count }.Max();
            for (int i = 0; i < max; i++)
                r3.Add(new { a = list1[i], b = list2[i], c = list3[i] });
            var time3 = DateTime.Now - start;
    
            Debug.WriteLine("r1 == r2: {0}", r1.SequenceEqual(r2));
            Debug.WriteLine("r1 == r3: {0}", r1.SequenceEqual(r3));
            Debug.WriteLine("time1 {0}", time1);
            Debug.WriteLine("time2 {0}", time2);
            Debug.WriteLine("time3 {0}", time3);
    

    The output:

    r1 == r2: True
    r1 == r3: True
    time1 00:00:00.0280393
    time2 00:00:00.0089870
    time3 00:00:00.0050041

    As expected, the .zip method has to do multiple iterations and becomes the slowest.

提交回复
热议问题