1

是否可以简洁地将值从 a 提取List<T>M x 1 double[,] 数组中,从而减少代码行数?

我有一个类型定义为:

public class Trajectory
{
    public Vector3 Position { get; set; }
    // ... more codes
}

Vector3 定义为:

    public struct Vector3
    {
        public float X;
        public float Y;
        public float Z;

        public Vector3(float x, float y, float z)
        {
            X = x;
            Y = y;
            Z = z;
        }
        // ... more vector3 operators
     }

目前我有List<Trajectory> trajectory。它最多有 80 个条目。我只想将每个条目的 X、Y、X 值存储trajectory240 x 1 double[,]数组(按 X、Y、Z 值的顺序)。

我目前的解决方案相当冗长且丑陋。它是这样的:

            // take a snapshot of current trajectory
            List<Entry> tempEntry = new List<Entry> (Entries);

            // create a temporary vector3Values
            List<Vector3> vector3Values = new List<Vector3>();

            foreach (Entry e in tempEntry)
            {
                vector3Values.Add(new Vector3(e.Position.X, e.Position.Y, e.Position.Z));
            } 

            /* Start an index at 0.
             * This is for foreach iteration to extract the value of x, y, and z from each vector3
             */
            int index = 0;

            // find the size of the list, in case max limit is changed
            int listCount = inputVector3.Count;

            /* set the length of the new array by multiplying the size of the list by 3.
             * We want:
             * [x1 x2 x3...xn y1 y2 y3...yn z1 z2 z3...zn]'.
             * Therefore, the size of the reshaped array is three times of the original array             *
             */
            int maxRowLength = listCount * 3;

            // create double[,] variable to store the reshaped data, three times the length of the actual list. 
            double[,] result = new double[maxRowLength, 1];

            // start going for each vector, then store the x components in the double[,] array.
            foreach (Vector3 vector3 in inputVector3)
            {
                result[index, 0] = vector3.X;
                index++;
            }

            /* continuing from the previous index value, start going for each vector, 
             * then store the z components in the double[,] array.
             */
            foreach (Vector3 vector3 in inputVector3)
            {
                result[index, 0] = vector3.Y;
                index++;
            }

            /* continuing from the previous index value, start going for each vector, 
             * then store the z components in the double[,] array.
             */
            foreach (Vector3 vector3 in inputVector3)
            {
                result[index, 0] = vector3.Z;
                index++;
            }

在一天结束时,我得到了我想要的。M x 1双 [,] 数组。我使用 double[,] 与我现在需要的 Matlab 的 MWArray 对象进行互操作。

所以,问题是,有没有一种简洁的方法来完成我在这里所做的事情?

已编辑:每秒需要多次进行此转换(感谢 Chris Sinclair 提出此问题),但是,目前这不是问题。

4

4 回答 4

3

您可以执行以下操作以避免循环三次:

var result = new double[entries.Count * 3, 1];

for (int i = 0; i < entries.Count; i++)
{
    result[i, 0] = entries[i].Position.X;
    result[i + entries.Count, 0] = entries[i].Position.Y;
    result[i + entries.Count * 2, 0] = entries[i].Position.Z;
}
于 2013-02-27T02:32:51.257 回答
1

如果您想要一种“快速/高效”的方法来执行此操作,则可以考虑避免使用 Linq 的一般枚举。虽然你说你最多只有 80 个条目,但我怀疑这是一个问题,除非你每秒执行这么多、很多、很多次。

无论如何,这是使用标准 for 循环的单次迭代,同时还最小化了元素查找和结构复制(我希望):

int length = inputVector3.Count;

double[,] result = new double[length * 3, 1];

for (int i = 0; i < length; i++)
{
    var vector = inputVector3[i];
    result[i, 0] = vector.X;
    result[i + length, 0] = vector.Y;
    result[i + length * 2, 0] = vector.Z;
}

return result;

如果这比其他选项更快(主要考虑数学和部分),我不肯定;最好只是尝试一下。i + lengthi + length * 2

于 2013-02-27T02:34:45.527 回答
0

我根本不喜欢我的回答,但你可以写一个这样的 linq 语句。我不能保证它会更快,但这是一种不同的尝试方法:

 List<Vector3> vectors = new List<Vector3>();
 //Select() will isolate the float value [X/Y/Z] of each type from the collection
 //Concat() will merge the selected float[]'s to make 
 //  one large array containing [x1,x2,x3...y1,y2,y3...z1,z2,z3...]
 float[] values = vectors.Select(e => e.X)
                         .Concat(vectors.Select(e => e.Y)
                         .Concat(vectors.Select(e => e.Z))).ToArray();
 for (int i = 0; i < values.Length; i++)
 {
      result[i, 0] = values[i];
 }
于 2013-02-27T02:14:34.460 回答
0

听起来 LINQ 命令 SelectMany 正是您正在寻找的。

给定列表轨迹,这就是我要做的:

double[] result = trajectory.SelectMany(t => new double[] { t.Position.X, t.Position.Y, t.Position.Z }).ToArray();

这就是说:从轨迹列表中,将 XY 和 Z 组成一个数组,然后将它们全部连接成一个大数组。我已经验证这可以保留顺序,但我不知道这是否会提高性能。

于 2013-02-27T02:19:19.463 回答