如何排列二维数组的形状?

时间:2019-02-10 22:06:11

标签: javascript arrays

我有一个根据字符串生成的二维数组(称为matrix):

131 673 234 103 018
201 096 342 965 150
630 803 746 422 111
537 699 497 121 956
805 732 524 037 331

解析后,它将成为下一个数组数组:

[
  [131, 673, 234, 103, 018],
  [201, 096, 342, 965, 150],
  [630, 803, 746, 422, 111],
  [537, 699, 497, 121, 956],
  [805, 732, 524, 037, 331]
]

但是,我需要对它进行操作,以使数组像这样:

[
  [131],
  [201,673],
  [630,096,234],
  [537,803,342,103],
  [805,699,746,965,018],
  [732,497,422,150],
  [524,121,111],
  [037,956],
  [331]
]

此数组是通过沿字符串或当前数组的2-dimensional对角线创建的up-left数组。

我认为可以对字符串进行操作(也许将其转换为一行),并在正确的位置用换行符重建该字符串,以使我的当前代码正常工作,但是我只是想不出如何实现它。

要创建数组,我正在使用以下代码:

matrix.split("\n").reduce((a, b) =>
{
    a.push(b.split(" ").map(x => parseInt(x)));
    return a;
}, []);

({matrix是保存我的字符串的变量的名称)

最好可以替换掉我的reducer功能,但是任何解决方案对我来说都是非常有益的。

4 个答案:

答案 0 :(得分:2)

根据您的方法,我进行了一些修改以将内部数组的每一项推到相应的对角线上。当我们推送新元素时,我已经使用Array::unshift()插入对角线数组的开头。

const matrix = "131 673 234 103 018\n201 096 342 965 150\n630 803 746 422 111\n537 699 497 121 956\n805 732 524 037 331";

let res = matrix.split("\n").reduce((acc, curr, idx1) =>
{
    curr.split(" ").forEach((n, idx2) =>
    {
        // Calculate idx of the diagonal this item belongs.
        let dIdx = idx2 + idx1;

        // Insert element on the related diagonal.
        acc[dIdx] = acc[dIdx] || [];
        acc[dIdx].unshift(parseInt(n));
    });

    return acc;

}, []);

console.log(res);

答案 1 :(得分:0)

您可以先从左侧开始,然后从左至右从底部开始,并获取数组的对角线值

function getDiagonal(x, y) {
    var result = [];
    while (x >= 0 && y < data[0].length) result.push(data[x--][y++]);
    return result;
}

var data = [[131, 673, 234, 103, 018], [201, 096, 342, 965, 150], [630, 803, 746, 422, 111], [537, 699, 497, 121, 956], [805, 732, 524, 037, 331]],
    result = [],
    i = 0, j = 1;
 
while (i < data.length) result.push(getDiagonal(i++, 0));
while (j < data[0].length) result.push(getDiagonal(data.length - 1, j++));

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:0)

这是我的镜头:

const input = `131 673 234 103 018
201 096 342 965 150
630 803 746 422 111
537 699 497 121 956
805 732 524 037 331`;

let matrix = input.split('\n').map(line => {
  return line.split(' ').map(elem => parseInt(elem.trim()));
});

let rows = matrix.length,
    cols = matrix[0].length,
    numDiags = rows + cols - 1,
    diagLimit = Math.max(matrix.length, matrix[0].length);

let diagMatrix = [...Array(numDiags)].map((_, diagNum) => {
  let diag = [];
  
  for (let i = 0; i < diagLimit; i++) {
    let r = (diagLimit - 1) - i,
        c = i - (diagLimit - 1) + diagNum;
    
    if (r >= 0 && c >= 0 && r < matrix.length && c < matrix[0].length) {
      diag.push(matrix[r][c]);
    }
  }
  
  return diag;
});

console.log(diagMatrix);

这遍历长度max(rows, cols)的每个对角线,该对角线与矩阵重叠,从而将重叠范围内的元素添加到输出数组。它还处理矩形矩阵,因此,如果仅处理正方形矩阵,则可以进行一些优化。

答案 3 :(得分:0)

这是您可以使用的技巧。这是矩阵索引的布局:

00  01  02  03

10  11  12

20  21

30

如果您注意到,则每个对角线的索引加起来等于一个数字,即结果数组的索引。

您可以使用此信息轻松地转换矩阵,如下所示:

const transform = (matrix, rows = matrix.length, cols = matrix[0].length) => {
    const result = [];

    for (let j = 0; j < cols; j++) {
        for (let i = 0; i < rows; i++) {
            const k = i + j; // this is the resulting index
            if (k >= result.length) result[k] = []; // create new rows on the fly
            result[k].push(matrix[i][j]);
        }
    }

    return result;
};

console.log(JSON.stringify(transform([ [131, 673, 234, 103,  18]
                                     , [201,  96, 342, 965, 150]
                                     , [630, 803, 746, 422, 111]
                                     , [537, 699, 497, 121, 956]
                                     , [805, 732, 524,  37, 331]
                                     ])));

希望有帮助。