是否可以使用for ... of和/或for ... in循环遍历嵌套数组?

时间:2018-11-09 13:59:00

标签: javascript arrays loops ecmascript-6 iteration

假设我有一个由嵌套数组组成的“矩形网格”,如下所示:

let board = [
  ['a0', 'a1', 'a2', 'a3', 'a4'],
  ['b0', 'b1', 'b2', 'b3', 'b4'],
  ['c0', 'c1', 'c2', 'c3', 'c4'],
  ['d0', 'd1', 'd2', 'd3', 'd4'],
];

我正在尝试遍历其列中的 ,因此结果将类似于'a0', 'b0', 'c0', 'd0', 'a1'... etc

我当然可以使用旧的for循环来做到这一点:

const iterateAcrossColumnsES5 = () => {
  for (let i = 0; i < board[0].length; i++) {
    for (let j = 0; j < board.length; j++) {
      console.log(board[j][i]);
    }
  }
}

但是我想尝试使其更简洁和可读性更好。我正在尝试在循环中使用 for .. of 和/或 for ..,但是我只能做到:

const iterateAcrossColumnsES6 = () => {
  for (let [i, item] of Object.entries(board)) {
    for(let row of board) {
      console.log(row[i])
    }
  }
}

但是它既不是简洁也不是可读,并且仅在 board 是“正方形”(父数组)的情况下才有效长度与其子项相同),否则迭代次数过多或不足。

有可能做到吗?我没有尝试使用map()forEach(),我很好。和他们在一起,但我很好奇我只能使用for..offor..in

6 个答案:

答案 0 :(得分:4)

js中没有内置的功能,但是有了两个小的辅助函数,您可以用一种非常优雅的方式编写循环:

function *chain(its) {
    for (let it of its)
        yield *it
}

function zip(arrays) {
    return arrays[0].map((e, i) => arrays.map(a => a[i]))
}

//

let board = [
  ['a0', 'a1', 'a2', 'a3', 'a4'],
  ['b0', 'b1', 'b2', 'b3', 'b4'],
  ['c0', 'c1', 'c2', 'c3', 'c4'],
  ['d0', 'd1', 'd2', 'd3', 'd4'],
]


console.log([...chain(board)].join(' '))


console.log([...chain(zip(board))].join(' '))

chain连接多个可迭代对象,以便您可以将它们作为一件事进行迭代,而zip则采用数组数组并将其转置。

答案 1 :(得分:2)

您可以使用map创建a0,b0....的数组,然后进一步缩小它。然后使用带有定界符,的join创建所需的结果

let board = [
  ['a0', 'a1', 'a2', 'a3', 'a4'],
  ['b0', 'b1', 'b2', 'b3', 'b4'],
  ['c0', 'c1', 'c2', 'c3', 'c4'],
  ['d0', 'd1', 'd2', 'd3', 'd4'],
];



var result = board.reduce((res, b) => res.map((elem, i) => elem + ',' + b[i])).join(',');
console.log(result);

答案 2 :(得分:2)

您可以更改面板的iterator,然后使用数组扩展或for...of来获取项目:

const board = [
  ['a0', 'a1', 'a2', 'a3', 'a4'],
  ['b0', 'b1', 'b2', 'b3', 'b4'],
  ['c0', 'c1', 'c2', 'c3', 'c4'],
  ['d0', 'd1', 'd2', 'd3', 'd4'],
];

board[Symbol.iterator] = function() {
  const rows = board.length;
  const max = rows * board[0].length;
  let current = 0;
  return {
    next: () => ({
      value: this[current % rows][parseInt(current / rows)],
      done: current++ === max
    })
  };
};

console.log([...board]);

for(const item of board) {
  console.log(item);
}

答案 3 :(得分:1)

您可以转置矩阵然后进行迭代。

const transpose = (r, a) => a.map((v, i) => (r[i] || []).concat(v));
let board = [['a0', 'a1', 'a2', 'a3', 'a4'], ['b0', 'b1', 'b2', 'b3', 'b4'], ['c0', 'c1', 'c2', 'c3', 'c4'],  ['d0', 'd1', 'd2', 'd3', 'd4']];

for (let a of board.reduce(transpose, [])) {
    for (let v of a) {
        console.log(v);
    }
}
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 4 :(得分:1)

使用for...in

var board = [
  ['a0', 'a1', 'a2', 'a3', 'a4'],
  ['b0', 'b1', 'b2', 'b3', 'b4'],
  ['c0', 'c1', 'c2', 'c3', 'c4'],
  ['d0', 'd1', 'd2', 'd3', 'd4']
];

var result = [];

for (var i in board)
    for (var j in board[i])
        result[+j * board.length + +i] = board[i][j];
    
console.log(result);

不建议在数组上使用for...inMDN Docs for reference

使用for...of

var board = [
  ['a0', 'a1', 'a2', 'a3', 'a4'],
  ['b0', 'b1', 'b2', 'b3', 'b4'],
  ['c0', 'c1', 'c2', 'c3', 'c4'],
  ['d0', 'd1', 'd2', 'd3', 'd4']
];

var result = [], i=0,j=0;

for (var arr of board) {
    for (var val of arr)
        result[j++ * board.length + i] = val;
    i++;j=0;
}

console.log(result);

如果内部数组的长度不均匀,则数组中将出现空值。因此需要过滤这些。

答案 5 :(得分:0)

这只有在有方形板的情况下才有用。

let board = [
  ["a0", "a1", "a2", "a3", "a4"],
  ["b0", "b1", "b2", "b3", "b4"],
  ["c0", "c1", "c2", "c3", "c4"],
  ["d0", "d1", "d2", "d3", "d4"],
  ["e0", "e1", "e2", "e3", "e4"]
];


for (const i in board) {
  for (const j in board) {
    console.log(board[j][i]);
  }
}