AVOlight
AVOlight

Reputation: 27

how to create a list of lists from one list using LINQ?

I do this multiple times every frame in my game. So looking for a way not to loop multiple times. Thanks for taking a look :)

    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};

Upvotes: 1

Views: 1763

Answers (2)

spender
spender

Reputation: 120518

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();

Upvotes: 2

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727027

Since you are producing three different results, you would need to write a loop yourself:

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);
}

You could potentially do that with List<T>.ForEach with side effects, but that would be the same thing:

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

Of course the best thing would be to avoid copying altogether. You could do it with a simple trick that passes a list of Vector3 objects along with the "extraction" functor, like this: instead of

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

and calling it

Process(listX);

you write

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

and call

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

Upvotes: 1

Related Questions