4

.Netに多次元配列/コレクション/データ型があり、その要素にベクトルでアクセスできます(次元数を簡単に変えるため)? このように (C#):

var array = new Smth<double>(capacity: new int[] {xCap, yCap, zCap});
array[new int[] {x, y, z}] = 10.0;

明確にするために:そのようなデータ型を手動で記述する方法を説明する必要はありません。

更新:

つまり、作成後ではなく、作成前に変更するということです。

// 3D array
var array = new Smth<double>(capacity: new int[] {xCap, yCap, zCap});
array[new int[] {x, y, z}] = 10.0;

// 6D array
var array = new Smth<double>(capacity: new int[] {xCap, yCap, zCap, tCap, vCap, mCap}); 
array[new int[] {x, y, z, t, v, m}] = 10.0;
4

1 に答える 1

6

そのような既製のコレクションはありませんが、次のようにDictionary<int[],double>と customを使用して簡単にエミュレートできますIEqualityComparerer<int[]>

class ArrayEq : IEqualityComparerer<int[]> {
    public bool Equals(int[] a, int[] b) {
        return a.SequenceEquals(b);
    }
    public int GetHashCode(int[] a) {
        return a.Aggregate(0, (p, v) => 31*p + v);
    }
}

この等価比較子を使用すると、次のことができます。

// The number of dimensions does not matter: if you pass a different number
// of dimensions, nothing bad is going to happen.
IDictionary<int[],double> array = new Dictionary<int[],double>(new ArrayEq());
array[new[] {1,2,3}] = 4.567;
array[new[] {1,2,-3}] = 7.654; // Negative indexes are OK
double x = array[new[] {1,2,3}]; // Get 4.567 back

特定の容量と特定の次元数が必要な場合は、 を変更しArrayEqて、データの検証をより厳密にすることができます。

コンパイル時に次元数がわかっている場合は、Tuple<...>配列の代わりにいずれかのクラスを使用して、パフォーマンスを向上させることができます。インデックスのベクトルを取得するために、多次元、たとえば、double[,,,]配列で拡張メソッドを定義することもできます。ただし、これら 2 つのアプローチはどちらも同じ柔軟性を提供しません (これは一般的なトレードオフです。多くの場合、柔軟性を減らすことでパフォーマンスを向上させることができます)。

編集:ストレージを事前に割り当て、インデックスの保存を避ける必要がある場合は、次のように多次元配列を自分で実装できます。

class MultiD<T> {
    private readonly T[] data;
    private readonly int[] mul;
    public MultiD(int[] dim) {
        // Add some validation here:
        // - Make sure dim has at least one dimension
        // - Make sure that all dim's elements are positive
        var size = dim.Aggregate(1, (p, v) => p * v);
        data = new T[size];
        mul = new int[dim.Length];
        mul[0] = 1;
        for (int i = 1; i < mul.Length; i++) {
            mul[i] = mul[i - 1] * dim[i - 1];
        }
    }
    private int GetIndex(IEnumerable<int> ind) {
        return ind.Zip(mul, (a, b) => a*b).Sum();
    }
    public T this[int[] index] {
        get { return data[GetIndex(index)]; }
        set { data[GetIndex(index)] = value; }
    }
}

これは、ジェネリックを使用する行優先のインデックス スキームの単純な実装です。

于 2013-04-26T18:29:43.793 に答える