二维数组之字形遍历
Zigzag traversal of a two-dimensional array
我需要以之字形遍历一个二维数组,并沿途挑选元素:
发件人:
[['','','',''],
['','','',''],
['','','',''],
['','','','']]
收件人:
['','','','','','','','','','','','','','','','']
我的方法是使用 for 循环,检查第一个数组的每个索引并将其与下一个数组的索引进行比较,然后如果该数字大一个,则将其推入新的一维数组。
解决此问题的最佳方法是什么?您是否有一些资源来了解有关此模式的更多信息?
更新的答案
此函数将以锯齿形方式合并数组。
这里我展示了 2 个具有不同数据类型值的数组的示例。
function zigZag(array) {
let arrayLength = array.length;
let arrayItemLength = array[0].length;
let result = [];
let flag = true;
for(let i = 0; i < (arrayLength + (arrayLength / 2) + 1) ; i++) {
if(i < arrayItemLength) {
let length = (i + 1);
let ii = i;
for(let j = 0; j < length; j++) {
if(flag == true) result.push(array[j][ii]);
else result.push(array[ii][j]);
ii-=1;
}
}else {
let ii = (i + 1) - arrayItemLength;
for(let j = arrayItemLength - 1; j > i - arrayItemLength; j--) {
if(flag == true) result.push(array[ii][j]);
else result.push(array[j][ii]);
ii+=1;
}
}
if(flag == true) flag = false;
else flag = true;
}
return result;
}
let array = [
["" , "" , "" , "" ],
["" , "" , "" , "" ],
["" , "" , "" , "" ],
["" , "" , "" , "" ],
];
let array_1 = [
[1, 3, 4, 10],
[2, 5, 9, 11],
[6, 8, 12, 15],
[7, 13, 14, 16],
];
console.log(zigZag(array)); // icons
console.log(zigZag(array_1)); // numbers
旧答案
试试这个,我想这就是你想要做的。
let array = [
[1, 3, 4, 10],
[2, 5, 9, 11],
[6, 8, 12, 15],
[7, 13, 14, 16],
];
function mergeArray(array) {
let merged = array.reduce((item, total) => [...total, ...item], []);
return merged.sort((a, b) => a - b);
}
let result = mergeArray(array);
console.log(result)
旧答案:
您可以对 javascript
数组使用 .flat()
方法。 Array.flat()
let array = [
[1, 3, 4, 10],
[2, 5, 9, 11],
[6, 8, 12, 15],
[7, 13, 14, 16],
]
const flatArray = array.flat()
flatArray.sort((a,b)=>a-b)
console.log(flatArray)
更新答案:
问题更新输出后
const items = [
[1, 3, 4, 10],
[2, 5, 9, 11],
[6, 8, 12, 15],
[7, 13, 14, 16],
];
/*const items = [
[ , , , ],
[ , , , ],
[ , , , ],
[ , , , ],
]*/
function zigZag(arr) {
let array = []
const itemCounts = arr.reduce((pre, cur)=> pre+cur.length,0)
for(let i=0; i<itemCounts; i+=1){
let round = []
for(let j=0; j<arr.length; j+=1){
if(arr[j].length){
round.push({
value: arr[j][0],
row:j
})
}
}
const minValue = Math.min(...round.map(item=>item.value))
const target = round.find(item=>item.value == minValue)
array.push(arr[target.row].shift())
}
return array;
};
console.log(zigZag(items))
我的理解是你想转换一个n×n数组如:
[ ['', '', '', '']
, ['', '', '', '']
, ['', '', '', '']
, ['', '', '', ''] ]
进入:
['','','','','','','','','','','','','','','','']
让我们将原始数组转换为“位置矩阵”,然后尝试描绘“之字形”:
[ [[0,0], [0,1], [0,2], [0,3]]
// ↙ ↗ ↙ ↗
, [[1,0], [1,1], [1,2], [1,3]]
// ↗ ↙ ↗ ↙
, [[2,0], [2,1], [2,2], [2,3]]
// ↙ ↗ ↙ ↗
, [[3,0], [3,1], [3,2], [3,3]]
// ↗ ↙ ↗ ↙
]
如果我们关注边缘,我们就可以开始制定一个模式:
[ [0,0]
, [1,0], /* … */ [0,1]
, [2,0], /* … */ [0,2]
, [3,0], /* … */ [0,3]
, [3,1], /* … */ [1,3]
, [3,2], /* … */ [2,3]
, [3,3] ]
现在我们需要计算出每条边之间的所有[x,y]
,并以相反的方向遍历每条边:
const inp1 = zigzag([ ['', '', '', '']
, ['', '', '', '']
, ['', '☝️', '', '']
, ['', '', '', ''] ]);
const inp2 = zigzag([ ['', '', '']
, ['', '', '']
, ['', '☝️', ''] ]);
const inp3 = zigzag([ ['', '']
, ['', ''] ]);
const inp4 = zigzag([ [''] ]);
console.log(`
[${String(inp1)}]
[${String(inp2)}]
[${String(inp3)}]
[${String(inp4)}]
`);
<script>
const zigzag = inp => {
const m = inp.length - 1;
const edges = [];
for (let x = 0; x <= m; x++) edges.push([x, 0]);
for (let x = 1; x <= m; x++) edges.push([m, x]);
return edges.flatMap(([x, y], i) => {
const path = [[x, y]];
for (let a = x, b = y; a != y && b != x;) path.push([--a, ++b]);
return (i % 2 ? path : path.reverse()).map(([x, y]) => inp[x][y]);
});
}
</script>
我需要以之字形遍历一个二维数组,并沿途挑选元素:
发件人:
[['','','',''],
['','','',''],
['','','',''],
['','','','']]
收件人:
['','','','','','','','','','','','','','','','']
我的方法是使用 for 循环,检查第一个数组的每个索引并将其与下一个数组的索引进行比较,然后如果该数字大一个,则将其推入新的一维数组。
解决此问题的最佳方法是什么?您是否有一些资源来了解有关此模式的更多信息?
更新的答案
此函数将以锯齿形方式合并数组。
这里我展示了 2 个具有不同数据类型值的数组的示例。
function zigZag(array) {
let arrayLength = array.length;
let arrayItemLength = array[0].length;
let result = [];
let flag = true;
for(let i = 0; i < (arrayLength + (arrayLength / 2) + 1) ; i++) {
if(i < arrayItemLength) {
let length = (i + 1);
let ii = i;
for(let j = 0; j < length; j++) {
if(flag == true) result.push(array[j][ii]);
else result.push(array[ii][j]);
ii-=1;
}
}else {
let ii = (i + 1) - arrayItemLength;
for(let j = arrayItemLength - 1; j > i - arrayItemLength; j--) {
if(flag == true) result.push(array[ii][j]);
else result.push(array[j][ii]);
ii+=1;
}
}
if(flag == true) flag = false;
else flag = true;
}
return result;
}
let array = [
["" , "" , "" , "" ],
["" , "" , "" , "" ],
["" , "" , "" , "" ],
["" , "" , "" , "" ],
];
let array_1 = [
[1, 3, 4, 10],
[2, 5, 9, 11],
[6, 8, 12, 15],
[7, 13, 14, 16],
];
console.log(zigZag(array)); // icons
console.log(zigZag(array_1)); // numbers
旧答案
试试这个,我想这就是你想要做的。
let array = [
[1, 3, 4, 10],
[2, 5, 9, 11],
[6, 8, 12, 15],
[7, 13, 14, 16],
];
function mergeArray(array) {
let merged = array.reduce((item, total) => [...total, ...item], []);
return merged.sort((a, b) => a - b);
}
let result = mergeArray(array);
console.log(result)
旧答案:
您可以对 javascript
数组使用 .flat()
方法。 Array.flat()
let array = [
[1, 3, 4, 10],
[2, 5, 9, 11],
[6, 8, 12, 15],
[7, 13, 14, 16],
]
const flatArray = array.flat()
flatArray.sort((a,b)=>a-b)
console.log(flatArray)
更新答案: 问题更新输出后
const items = [
[1, 3, 4, 10],
[2, 5, 9, 11],
[6, 8, 12, 15],
[7, 13, 14, 16],
];
/*const items = [
[ , , , ],
[ , , , ],
[ , , , ],
[ , , , ],
]*/
function zigZag(arr) {
let array = []
const itemCounts = arr.reduce((pre, cur)=> pre+cur.length,0)
for(let i=0; i<itemCounts; i+=1){
let round = []
for(let j=0; j<arr.length; j+=1){
if(arr[j].length){
round.push({
value: arr[j][0],
row:j
})
}
}
const minValue = Math.min(...round.map(item=>item.value))
const target = round.find(item=>item.value == minValue)
array.push(arr[target.row].shift())
}
return array;
};
console.log(zigZag(items))
我的理解是你想转换一个n×n数组如:
[ ['', '', '', '']
, ['', '', '', '']
, ['', '', '', '']
, ['', '', '', ''] ]
进入:
['','','','','','','','','','','','','','','','']
让我们将原始数组转换为“位置矩阵”,然后尝试描绘“之字形”:
[ [[0,0], [0,1], [0,2], [0,3]]
// ↙ ↗ ↙ ↗
, [[1,0], [1,1], [1,2], [1,3]]
// ↗ ↙ ↗ ↙
, [[2,0], [2,1], [2,2], [2,3]]
// ↙ ↗ ↙ ↗
, [[3,0], [3,1], [3,2], [3,3]]
// ↗ ↙ ↗ ↙
]
如果我们关注边缘,我们就可以开始制定一个模式:
[ [0,0]
, [1,0], /* … */ [0,1]
, [2,0], /* … */ [0,2]
, [3,0], /* … */ [0,3]
, [3,1], /* … */ [1,3]
, [3,2], /* … */ [2,3]
, [3,3] ]
现在我们需要计算出每条边之间的所有[x,y]
,并以相反的方向遍历每条边:
const inp1 = zigzag([ ['', '', '', '']
, ['', '', '', '']
, ['', '☝️', '', '']
, ['', '', '', ''] ]);
const inp2 = zigzag([ ['', '', '']
, ['', '', '']
, ['', '☝️', ''] ]);
const inp3 = zigzag([ ['', '']
, ['', ''] ]);
const inp4 = zigzag([ [''] ]);
console.log(`
[${String(inp1)}]
[${String(inp2)}]
[${String(inp3)}]
[${String(inp4)}]
`);
<script>
const zigzag = inp => {
const m = inp.length - 1;
const edges = [];
for (let x = 0; x <= m; x++) edges.push([x, 0]);
for (let x = 1; x <= m; x++) edges.push([m, x]);
return edges.flatMap(([x, y], i) => {
const path = [[x, y]];
for (let a = x, b = y; a != y && b != x;) path.push([--a, ++b]);
return (i % 2 ? path : path.reverse()).map(([x, y]) => inp[x][y]);
});
}
</script>