我应该使用哪种算法从多维数组中提取数组?

时间:2013-07-08 21:14:50

标签: arrays algorithm language-agnostic

例如,我想从这样的数组中提取子数组,其中arr是一个三维数组,"all"表示该索引位置的所有可能值都是选自:

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

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

2 个答案:

答案 0 :(得分:2)

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

  1. 给定N - dim数组的实例,找到N
  2. 根据N - dim数组和k < N的实例,查找维k
  3. 中的项目数
  4. 给定N - dim数组A的实例和N整数I的向量,在项目中由索引定义的位置获取或设置项目向量。例如,如果向量为I = {2, 3, 4},则需要执行从3-D数组A[2, 3, 4]和向量A获取I的操作。
  5. 如果定义尺寸D的向量M,则需要有一个用于构建M维数组的操作,每个维度都采用相应项目的大小向量。例如,如果向量D = {3, 4},则需要创建一个尺寸为3和4的二维数组的操作。
  6. 通过构建向量FD来预处理请求,如下所示:

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

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

    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;
    }
    

答案 1 :(得分:0)

即使维度的数量是可变的,除非我遗漏了什么,否则这看起来相当简单?

看起来您可以解析第二个参数,找出结果的维度,然后将数据复制到结果中。复制数据并不困难,因为您只能找到arr子阵列的长度,或者如果语言不支持它,您可以将维度作为参数传入。