如何使用 LINQ 从一个列表创建列表列表

本文关键字:列表 一个 创建 何使用 LINQ | 更新日期: 2023-09-27 18:32:03

我在游戏中的每一帧都这样做多次。因此,寻找一种不循环多次的方法。感谢您查看:)

    List<Vector3> listVectors = new List<Vector3>();
    for (int i = 0; i < 2000; i++) {
        listVectors.Add(new Vector3(i,i,i));
    }
    var listX = from v in listVectors select v.x;
    var listY = from v in listVectors select v.y;
    var listZ = from v in listVectors select v.z;
    // Is it possible to create this without looping multiple times
    List<IEnumerable<float>> listV = new List<IEnumerable<float>>{listX,listY,listZ};

如何使用 LINQ 从一个列表创建列表列表

List<List<float>> lists = listVectors
    .SelectMany(v => new[]{
        new{k = 'x', v = v.x},
        new{k = 'y', v = v.y},
        new{k = 'z', v = v.z}})
    .GroupBy(x => x.k)
    .OrderBy(g => g.Key)
    .Select(g => g.Select(x => x.v).ToList())
    .ToList();

由于您正在生成三个不同的结果,因此您需要自己编写一个循环:

List<float> listX = new List<float>(listVectors.Count);
List<float> listY = new List<float>(listVectors.Count);
List<float> listZ = new List<float>(listVectors.Count);
foreach (var vec in listVectors) {
    listX.Add(vec.x);
    listY.Add(vec.y);
    listZ.Add(vec.z);
}

您可能会使用带有副作用List<T>.ForEach这样做,但这将是一回事:

listVectors.ForEach(vec => {
    listX.Add(vec.x);
    listY.Add(vec.y);
    listZ.Add(vec.z);
});

当然,最好的办法是完全避免复制。你可以用一个简单的技巧来做到这一点,该技巧传递Vector3对象列表以及"提取"函子,如下所示:

而不是
void Process(IList<float> data) {
    foreach (float f in data) {
        // Do something with f
    }
}

并称它

Process(listX);

你写

void Process(IList<Vector3> data, Func<Vector3,float> extract) {
    foreach (Vector3 v in data) {
        float f = extract(v);
        // Do something with f
    }
}

并致电

Process(listVectors, v => v.x);