1

List<T>aからMx1 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エントリあります。trajectory各エントリのX、Y、X値のみを240 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オブジェクトとの相互運用性のためにdouble[、]を使用しています。

だから、問題は、私がここでやっていることを達成するための簡潔な方法はありますか?

編集済み:この変換は1秒間に何度も必要になります(この問題を提起してくれたChris Sinclairに感謝します)が、現時点では問題ではありません。

4

4 に答える 4

3

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エントリしかないということですが、これを1秒間に何度も何度も実行しない限り、問題になるとは思えません。

とにかく、要素のルックアップと構造体のコピーを最小限に抑えながら、標準の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 + lengthではありません(主にと部分の数学について考えていますi + 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 に答える