使用轴坐标的整数坐标动态创建有限的n维坐标系

时间:2016-01-06 14:16:01

标签: javascript arrays algorithm dynamic dimensions

我试图通过首先创建轴坐标来动态创建有限n维坐标系中的位置列表。系统仅将整数作为坐标值。轴坐标是AxCrd对象。 AxCrd对象有两个属性:

  1. AxCrd.dim是坐标维度的句柄或名称。例如," x"或" y"。
  2. AxCrd.crd是坐标的值。它是一个整数。例如,-4或3。
  3. 我试图编写一个函数,该函数接受所有生成的AxCrd对象作为输入,并输出n维空间中我尝试创建为Crd的所有位置的列表-objects。 Crd-object有两个属性:

    1. Crd.dims是一个包含坐标所有维度句柄的数组。此数组的长度为n,即等于维数。

    2. Crd.crds是一个包含上述尺寸的所有坐标值的数组。该数组的排序很重要,因为坐标的维度应该与坐标值具有相同的元素编号。 IE浏览器。如果尺寸" z"是第二个元素,然后crds [2]是维度" z"的坐标值。

    3. 例如,假设我使用这些构造函数:

      function AxCrd(dim,crd) { this.dim = dim, this.crd = crd }
      function Crd(dims,crds) { this.dims = dims, this.crds = crds }
      

      在我的实际用途中,大多数尺寸都有九个值:四个负值,四个正值和一个零值。但为了简洁起见,我们假设我有三个维度:

      var input = [];
      input.push(new AxCrd("x", -1));
      input.push(new AxCrd("x", 1));
      input.push(new AxCrd("y", -1));
      input.push(new AxCrd("y", 1));
      input.push(new AxCrd("z", -1));
      input.push(new AxCrd("z", 1));
      input.push(new AxCrd("d", -1));
      input.push(new AxCrd("d", 1));
      

      如您所见,有三个维度,每个维度只有两个坐标值。我尝试编写一个函数,在给定上述输入的情况下,将创建这样的新Crd对象:

      var ret = [];
      ret.push(new Crd(["x","y","z","d"],[-1,-1,-1,-1]));
      ret.push(new Crd(["x","y","z","d"],[ 1,-1,-1,-1]));
      ret.push(new Crd(["x","y","z","d"],[-1, 1,-1,-1]));
      ret.push(new Crd(["x","y","z","d"],[ 1, 1,-1,-1]));
      ret.push(new Crd(["x","y","z","d"],[-1,-1, 1,-1]));
      ret.push(new Crd(["x","y","z","d"],[ 1,-1, 1,-1]));
      ret.push(new Crd(["x","y","z","d"],[-1, 1, 1,-1]));
      ret.push(new Crd(["x","y","z","d"],[ 1, 1, 1,-1]));
      ret.push(new Crd(["x","y","z","d"],[-1,-1,-1, 1]));
      ret.push(new Crd(["x","y","z","d"],[ 1,-1,-1, 1]));
      ret.push(new Crd(["x","y","z","d"],[-1, 1,-1, 1]));
      ret.push(new Crd(["x","y","z","d"],[ 1, 1,-1, 1]));
      ret.push(new Crd(["x","y","z","d"],[-1,-1, 1, 1]));
      ret.push(new Crd(["x","y","z","d"],[ 1,-1, 1, 1]));
      ret.push(new Crd(["x","y","z","d"],[-1, 1, 1, 1]));
      ret.push(new Crd(["x","y","z","d"],[ 1, 1, 1, 1]));
      

      如何在n维空间中执行此操作?

4 个答案:

答案 0 :(得分:1)

如果我理解了您的问题,那么您需要一张包含所有维度名称的地图(称为dim_map应为dim_map['x'] = 0; dim_map['y'] = 1;...)。 然后,当您进行转换时,使用密钥dims,查找index = dim_map[AxCrd.dim]的索引,并将这些值分配给相应的元素(Crd.crds[index] = AxCrd.crd)。

我不完全确定这是你想要的,因为你的例子似乎令人困惑。我不确定为什么你为每个AxCrd构建两个Crds或者为什么其他一些值似乎会改变。

答案 1 :(得分:1)

递归似乎是处理这类问题的正确方法。这是一个简单的递归函数,它返回结果的数组。它还将维度的名称存储在作为函数参数传递的数组中。

function rec(i, input, dimensions)
{
   // find the name of the current dimension
   var currentd = input[i].dim;

   dimensions.push(currentd);

   // find how many elements in the current dimension
   var j = i;
   while (j < input.length && input[j].dim == currentd) ++j;

   // create a tail of results
   var tail = [];
   if (j < input.length) {
      tail = rec(j, input, dimensions);
   }

   // create a result by appending tail to all possible coordinates in the current dimension
   var result = [];
   for (; i < j; i++) {
       if (tail.length == 0) {
           result.push([input[i].crd]);
       } else {
           for (var k = 0; k < tail.length; k++) {
               result.push([input[i].crd].concat(tail[k]));
           }
       }
   }
   return result;
}

此函数不会创建Crd个对象,但您可以轻松修改它。用法示例:

var dimensions = [];
var result = rec(0, input, dimensions);
console.log(JSON.stringify(dimensions));
for (var i = 0; i < result.length; i++) {
  console.log(JSON.stringify(result[i]));
}

输出(假设input与示例中一样):

["x","y","z","d"]
[-1,-1,-1,-1]
[-1,-1,-1,1]
[-1,-1,1,-1]
[-1,-1,1,1]
[-1,1,-1,-1]
[-1,1,-1,1]
[-1,1,1,-1]
[-1,1,1,1]
[1,-1,-1,-1]
[1,-1,-1,1]
[1,-1,1,-1]
[1,-1,1,1]
[1,1,-1,-1]
[1,1,-1,1]
[1,1,1,-1]
[1,1,1,1]

答案 2 :(得分:0)

看起来您正在寻找每个子阵列或Cartesian product项目的所有可能组合。这可以递归计算:

function product(array) {
    if (array.length == 0) return [[]];

    var head = array[0];
    var tail = product(array.slice(1));
    var res = [];

    for (var i = 0; i < head.length; i++) {
        for (var j = 0; j < tail.length; j++) {
            res.push([head[i]].concat(tail[j]));
        }
    }

    return res;
}

Ans像这样使用它:

var input = [
    [-1, 1],    // x
    [-1, 1],    // y
    [-1, 1],    // z
    [-1, 1],    // d
];

var prod = product(input);

for (var i = 0; i < prod.length; i++) {
    console.log(i, prod[i]);
}

上述函数在假设传递的数组是数组数组的情况下工作。没有试图检测到它。

您可以将生成的数组添加到列表中,而不是打印。我不确定为什么每次添加坐标时都会创建一个新的坐标系。难道你不应该只创建一次坐标系并传递一个参考吗?我也是第二个索林,你可能想要一个逐字母查找的地图。你的班级设计似乎不必要地复杂。

答案 3 :(得分:0)

我打算做的事情似乎几乎可以通过以下功能实现:

function makeAllCoordinates(arr) {
  if (arr.length === 0) { return []; }
  else if (arr.length === 1) { return arr[0]; }
  else {
    var result = [];
    var allCases = makeAllCoordinates(arr.slice(1));
    for (var c in allCases) {
      for (var i = 0; i < arr[0].length; i++) {
        result.push((arr[0][i] + allCases[c]).split(",")); }}
    return result; }}

结果是9×9×9×9×3×3 = 59049个成员的阵列。这个数字是正确的。但是,每个数组只有一个成员,这是一个由六个重复的“[object Object]”组成的字符串。我需要它们是六个AxCrd对象的唯一数组而不是这样的字符串。数组的顺序无关紧要。以这种方式修改这个功能难吗?

无论如何,我希望这个回复能够清楚地表明我正在做的事情。