从List <classa>高效创建List <classb>?

时间:2017-07-13 20:12:09

标签: c# list constructor

我有来自ClassA的对象,并希望使用它们来创建ClassB的对象。如果我一次只处理一个对象,我知道如何做到这一点:

ClassA object1 = new ClassA();
ClassB object2 = new ClassB(object1);

class ClassA
{
    public DateTime Timestamp;
    public double X;
    public double Y;
    public double Z;

    public ClassA()
    {
       // other stuff
    }
}

class ClassB
{
    public DateTime Timestamp;
    public double X;

    public ClassB(ClassA A)
    {
        Timestamp = A.Timestamp;
        X = A.X;
    }
}

但是,我正在寻找使用对象列表的最佳方法。我想获取类型ClassA的列表,并创建一个类型为ClassB的列表:

List<ClassA> list_of_classA = new List<ClassA>();
List<ClassB> list_of_classB = ????

4 个答案:

答案 0 :(得分:5)

除了Markus演示的查询样式语法之外,您还可以使用lambda样式语法将ClassA列表投影到ClassB

var listOfClassB = list_of_classA.Select(x => new ClassB(x)).ToList()

答案 1 :(得分:3)

您可以使用Linq将列表投影到类型为ClassB的新列表:

List<ClassB> list_of_classB = (from x 
                               in list_of_classA
                               select new ClassB(x)).ToList();

首先,你可以在Linq here上找到很多好的样本。

答案 2 :(得分:2)

只是为了做第三种方式:

List<ClassA> list_of_classA = new List<ClassA>();
List<ClassB> list_of_classB = new List<ClassB>();

foreach (ClassA item in list_of_classA)
        {
            list_of_classB.Add(new ClassB(item));
        }

如果不使用Linq或Lambda表达式,这将完成同样的事情。如果可能,您很可能希望使用提供的其他2个答案中的一个。但是,如果您不熟悉Linq或Lambda表达式,那么这可能会有所帮助。

答案 3 :(得分:2)

您很可能希望像其他人建议的那样使用Select

也就是说,如果你想要做的唯一事情就是对列表进行转换并且性能非常重要,那么List有一个你可以使用的方法ConvertAll

List<ClassA> list_of_classA = new List<ClassA>();
List<ClassB> list_of_classB = list_of_classA.ConvertAll((ClassA a) => new ClassB(a));

您可以阅读有关使用Select和ConvertAll之间差异的更多信息 here关于绩效,here关于他们的差异。

由于ConvertAll是较不通用的(仅适用于列表),因此它应该比更通用的Select选项更快。我尝试通过一些测试来反驳这个想法。

我在A列表中创建了一个包含5和1000万个对象的列表,并测试了ConvertAll和Select选项并获得了这些结果:

enter image description here enter image description here

y轴以ms为单位。

所以数据似乎表明ConvertAll实际上要快一点。但是,我的代码可能会有一些导致这些差异的问题,所以请耐心等待。

这是我使用的代码。编译发布到x64。 (还修改了ListA,以便它实际上有一个合适的构造函数)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace lekstuga
{
    class Program
    {
        static void Main(string[] args)
        {
            int loops = 10000000;

            for (var n = 0; n < 4; n++)
            {

                Stopwatch stopwatch;

                List<ClassA> listOfClassA2 = new List<ClassA>();
                List<ClassB> listOfClassB2 = new List<ClassB>();

                for (int i = 0; i < loops; i++)
                {
                    listOfClassA2.Add(new ClassA(DateTime.Now, 1, 2, 3));
                }

                stopwatch = Stopwatch.StartNew(); //creates and start the instance of Stopwatch
                listOfClassB2 = listOfClassA2.ConvertAll((ClassA a) => new ClassB(a));
                stopwatch.Stop();

                Console.WriteLine("ConvertAll " + stopwatch.ElapsedMilliseconds + "ms");


                List<ClassA> listOfClassA = new List<ClassA>();
                List<ClassB> listOfClassB = new List<ClassB>();

                for (int i = 0; i < loops; i++)
                {
                    listOfClassA.Add(new ClassA(DateTime.Now, 1, 2, 3));
                }

                stopwatch = Stopwatch.StartNew(); //creates and start the instance of Stopwatch
                listOfClassB = listOfClassA.Select(x => new ClassB(x)).ToList();
                stopwatch.Stop();

                Console.WriteLine("Select " + stopwatch.ElapsedMilliseconds + "ms");
            }
            Console.ReadLine();
        }

        class ClassA
        {
            public DateTime Timestamp;
            public double X;
            public double Y;
            public double Z;

            public ClassA(DateTime t, double x, double y, double z)
            {
                Timestamp = t;
                X = x;
                Y = y;
                Z = z;
            }
        }

        class ClassB
        {
            public DateTime Timestamp;
            public double X;

            public ClassB(ClassA A)
            {
                Timestamp = A.Timestamp;
                X = A.X;
            }
        }
    }
}

最后,关于Select的注释,虽然它是懒惰的但在实际需要使用之前不执行.ToList()会强制LINQ立即计算数据,因此Select和ConvertAll在这方面具有可比性。