2

例如,我想从这样的数组中提取子数组,其中arr是一个 3 维数组,"all"这意味着选择了该索引位置的所有可能值:

getSubArray(arr, ["all","all",1])arr返回 arr的二维切片,索引来自["all", "all", 1]

getSubArray(arr,["all",2,2])应该从 中返回一个一维数组arr,其中索引arr["all", 2, 2]

4

2 回答 2

2

一种相对简单的方法是将此任务视为维度的 K 元组到维度N的 K元组的递归映射M < N。由于这与语言无关,因此需要以您的目标语言提供以下工具:

  1. 给定一个N-dim 数组的实例,找到N
  2. 给定一个N-dim 数组和 a的实例k < N,找出维度中的项目数k
  3. 给定一个N-dim 数组的实例A和一个N整数向量I,在向量中的索引定义的位置获取或设置项目。例如,如果向量是I = {2, 3, 4},则需要A[2, 3, 4]从 3-D 数组A和向量中获取一个操作I
  4. D给定一个大小定义维度的向量M,需要一个构造维度数组的操作M,每个维度取向量中对应项的大小。例如,如果是向量D = {3, 4},则需要有一个操作来创建一个维度为 3 和 4 的二维数组。

通过构造向量对请求进行预处理FD如下所示:

  • 对于请求"all"位置的每个项目,以及iF[i] = -1D[i] = size(dimension[i])
  • 对于请求k位置的每个数字项,并且.iF[i] = kD[i] = 0
  • 通过获取所有非固定索引并将它们传递给数组构造函数(上面的先决条件四),为结果创建一个数组。

现在您的递归过程应该看起来相对简单:

void RecursiveCopy(Vector F, Vector D, Array S, Vector SI, int sp, Array T, Vector TI, int tp) {
    if (pos != TS.size) {
        if (F[sp] != -1) {
            // This is an "all" dimension
            for (int i = 0 ; i != D[sp] ; i++) {
                SI[sp] = i;
                TI[tp] = i;
                RecursiveCopy(F, D, S, SI, sp+1, T, TI, tp+1);
            }
        } else {
            // This is a fixed dimension
            SI[sp] = F[sp];
            RecursiveCopy(F, D, S, SI, sp+1, T, TI, tp);
        }
    } else {
        // Read from the source at indexes defined by vector SI
        var value = S.get(SI);
        // Write to the destination at indexes defined by vector TI
        T.setValue(TI, value); // Prerequisite 3
    }
}

getSubarray看起来像这样:

Array getSubarray(Array S, Vector<string> request) {
    Vector F = Vector[S.Size]; // The number of dimensions in A; prerequisite 1
    Vector D = Vector[S.Size]; // The number of dimensions in A
    Assert(request.Size == S.Size); // Request must have N items
    int k = 0;
    Vector resDim;
    for (int i = 0 ; i != req.Size ; i++) {
        if (req[i] == "all") {
            k++;
            F[i] = -1;
            D[i] = A.dimensionOf(i); // Prerequisite 2
            resDim.Add(D[i]);
        } else {
            F[i] = ParseInteger(req[i]);
            D[i] = -1;
        }
    }
    Array T = Array(resDim); // Prerequisite #4
    Vector SI = Vector[S.Size];
    Vector TI = Vector[k];
    RecursiveCopy(F, D, S, SI, 0, T, TI, 0);
    return T;
}
于 2013-07-08T21:47:08.037 回答
0

即使维数是可变的,除非我遗漏了什么,否则这似乎相当简单?

似乎您可以只解析第二个参数,找出结果的维度应该是什么,然后将数据复制到结果中。复制数据并不难,因为您可以找到子数组的长度,arr 或者如果语言不支持它,您可以将维度作为参数传入。

于 2013-07-08T21:30:39.747 回答