How to make a variable structure component?

Not sure if I ask this right or is it even possible. I feel that in order to explain my question, it is best to ask in the code in the appropriate places, so please see My comments in the fragment below.

I wonder how to achieve this without creating a new list of values โ€‹โ€‹for each iteration I. I believe that this is not necessary.

A larger picture of this cycle is the construction of individual measurements of three-dimensional points on three new 2D graphics. Hope this makes sense.

for (int i = 0; i < 3; i++) // 3 iterations (X,Y;Z) { // what here? how to make the data component of Vector3D a variable for (int k = 0; k <= Points.Count - 1; k++) { Vector2D TL = new Vector2D(); TL.x = ((1 / (float)FrameCount.Sum()) * k); TL.y = Points[k].x; // on i = 0 want Points[k].x // on i = 1 want Points[k].y // on i = 2 want Points[k].z TimelinePoints.Add(TL); // just collect to a flat list for now } } 
+5
source share
3 answers

One option is to have an array of extraction functions that you could apply to points. Then you can use the LINQ Select overload, which takes Func<TInput, int, TOutput> , to generate the sequence of values โ€‹โ€‹you want to add and add it to TimeLinePoints in this way.

 // Possibly store this in a static variable somewhere var extractors = new Func<Point, float>[] { p => px, p => py, p => pz }; // Just do this once; store the result as a float for simplicity when dividing later. float frameSum = FrameCount.Sum(); foreach (var extractor in extractors) { TimeLinePoints.AddRange(Points.Select((point, index) => new Vector2D(index / frameSum, extractor(point)); } 

(You could go even further using SelectMany potentially, but where I would start ...)

+4
source

A significantly larger pedestrian approach than John Skeet's answer would be to modify the Point structure to include an indexer, assuming this is an option:

 public struct Point { float x; float y; float z; public float this[int index] { get { switch (index) { case 0: return x; case 1: return y; case 2: return z; default: throw new IndexOutOfRangeException(); } } set { switch (index) { case 0: x = value; break; case 1: y = value; break; case 2: z = value; break; default: throw new IndexOutOfRangeException(); } } } } 

Then you can assign the correct field according to the value of your loop counter, for example:

 for (int k = 0; k < Points.Count; k++) { Vector2D TL = new Vector2D(); TL.x = ((1 / (float)FrameCount.Sum()) * k); TL.y = Points[k][i]; TimelinePoints.Add(TL); // just collect to a flat list for now } 
+4
source

An alternative way is to use Linq to archive this:

 Points //foreach point create 3 Vector2D with X, Y and Z coordinate .SelectMany((p, index) => new [] { new Vector2D(index / frameSum, pX), new Vector2D(index / frameSum, pY), new Vector2D(index / frameSum, pZ) }) //unfurl IEnumerable<IEnumerable<Vector2D>> to IEnumerable<Vector2D> .Select(v => v) .ToList(); 
+3
source

Source: https://habr.com/ru/post/1275435/


All Articles