0

我正在使用的二维数组的每一行都有不同的长度,例如:

var a = [2, 5, -12, 9];
var b = [54.0, 0.3];
var c = ["tree", "sun", "pool"]
var all = [a, b, c]

二维数组中的任何行有时都可能为零。上面的数组只是一个例子。

我想做的是从每个人的每一行中获取一个值,用这些值做一些事情,然后得到另一个值的组合,等等。

例子:

//IF ALL ROWS HAVE CONTENT
var values = [all[0][0], all[1][0], all[2][0]];
//do something with it
values = [all[0][0], all[1][0], all[2][1]];
//do something with it
......
values = [all[0][3], all[1][1], all[2][2]];
//do something with it

//IF FIRST AND THRID ROWS HAVE CONTENT, THE SAMPLE OUTPUT
var values = [all[0][0], all[2][0]];
values = [all[0][0], all[2][1]];
......
values = [all[0][3], all[2][2]];

//IF ONLY SECOND ROWS HAVE CONTENT, THE SAMPLE OUTPUT
var values = [all[1][0]];
values = [all[1][1]];

这是我对代码逻辑流程的想法

//count how many rows are not empty
var arrayCount = 0;
for(var i=0; i < all.length; i++){
   if(all[i].length !== 0){
      arrayCount++;
  }
}
//store the combination of values each time
var values = [];
//reference for rows
var x; var y;
//differentiate the looping based on the number of unempty rows
switch(arrayCount){
   //one unempty row
   case 1:
      //figure out which one is not empty and set a's pointer to it
      for(var q = 0; q < x.length; q++){
         values.push(x[q]);
         //do something with it
         values.splice(1, 0);
      }
      break;
   case 2:
      //figure out which one are not empty and set a and b's pointer to them (don't know how, maybe using two loops for each row?)
      for(var q = 0; q < x.length; q++){
         values.push(x[q]);
         for(var p = 0; p < y.length; p++){
            values.push(y[p]);
            //do something with it
            values.splice(1, 1);
         }
         values.splice(1, 0);
      }
      break;
   case 3:
      //set pointers to all the rows
      for(var q = 0; q < x.length; q++){
         values.push(x[q]);
         for(var p = 0; p < y.length; p++){
            values.push(y[p]);
            for(var r = 0; r < z.length; r++){
               values.push(z[r]);
               //do something with it
               values.splice(1, 2);
            }
            values.splice(1, 1);
         }
         values.splice(1, 0);
      }
      break;
}

恐怕整个代码太长了,并且在开关中有一些重复的代码。可以简化吗?

我确实看到了同样问题的帖子,我尝试了它的答案。不幸的是,我正在编码的平台(Fandom)不支持这个生成器功能。我问,它只支持 Javascript 到 ES3 或 ES4。

谢谢你看这个问题!

4

3 回答 3

0

这是一个处理空数组并且不使用生成器函数的解决方案。

var combinations = all.reduce(function (previous, current) {

    if (current.length === 0)
        return previous;

    if (previous.length === 0)
        return current;

    const accumulate = current.map(function (x){

        return previous.map(function(y) {

            // Make one array if the accumulated result is an array
            if (y.length > 0)
                return y.concat(x);

            return [x, y];
        });
    });

    // Flatten combinations
    return accumulate.reduce( function (acc, x) {
        return acc.concat(x);
    });
});
于 2019-05-24T03:07:17.533 回答
0

您可以采用递归方法,获取数组数组并迭代每个内部数组并移交收集的项目数组,直到没有更多可用数组为止。

function getCartesian(array) {
    function iter(temp)  {
        var i = temp.length, j;
        if (i >= array.length) {
            return result.push(temp);
        }
        for (j = 0; j < array[i].length; j++) {
            iter(temp.concat(array[i][j]));
        }
    }

    var result = [];
    iter([]);
    return result;
}

console.log(getCartesian([[2, 5, -12, 9], [54.0, 0.3], ["tree", "sun", "pool"]]).map(a => a.join(' ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }

一个功能

function getCartesian(array) {
    var i, j,
        first = array.shift(),
        temp = [],
        result = [];

    if (!first) return;
    if (!array.length) return first;
    temp = getCartesian(array);

    for (i = 0; i < first.length; i++)
        for (j = 0; j < temp.length; j++)
            result.push([first[i]].concat(temp[j]));

    return result;
}

console.log(getCartesian([[2, 5, -12, 9], [54.0, 0.3], ["tree", "sun", "pool"]]).map(a => a.join(' ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }

于 2019-05-24T06:43:54.103 回答
0

我通过babel 的在线 repl对类似问题运行了这个答案,并得到了丑陋但可操作的代码,似乎可以满足您的要求。

警告:此引用Symbol.iterator在 ES4 中可能不可用。我没有研究过。如果您想修改 babel 设置以实现兼容性,上面的 babel 链接包括原始解决方案和此转换。

我最初没有发布这个,因为看起来人们已经使用相同的算法回答了你的问题而没有编译的丑陋,但是既然你问了......

这是针对您的示例输入运行的结果:

const a = [2, 5, -12, 9];
const b = [54.0, 0.3];
const c = ["tree", "sun", "pool"];
const all = [a, b, c];

function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }

function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }

function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }

function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }

var makeCartesian = function makeCartesian() {
  var t = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  return function (a) {
    for (var _len = arguments.length, more = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      more[_key - 1] = arguments[_key];
    }

    return a === undefined ? [t] : a.flatMap(function (x) {
      return makeCartesian([].concat(_toConsumableArray(t), [x])).apply(void 0, more);
    });
  };
};

var cartesian = makeCartesian();
console.log(cartesian.apply(void 0, _toConsumableArray(all)));

于 2019-05-25T00:14:51.480 回答