在 JavaScript 中按对角键重新排列/转置数组项
Rearrange / transpose array items by keys diagonally in JavaScript
我有一个 字符串数组 ,例如:
var arr=["dog", "cat", "bear", "wolf", "lynx", "hare", "sheep", "owl", "hen"];
要引用这些值中的任何一个,都有从0到8的对应键,即arr[3]对应于“wolf”。实际数组的项目数量可能会有所不同,并且其中有超过 100 个项目。在这个例子中有 9 [0,1,2,3,4,5,6,7,8]
.
我想要完成的是按对角键重新排列项目,即从:
[0,1,2,
3,4,5,
6,7,8]
进入:
[0,2,5,
1,4,7,
3,6,8]
即进入[0,2,5,1,4,7,3,6,8]
,因此也从原来的相应值的序列:
var arr=["dog", "cat", "bear", "wolf", "lynx", "hare", "sheep", "owl", "hen"];
导致重新排列的值:
var arr2=["dog", "bear", "hare", "cat", "lynx", "wolf", "owl", "sheep", "hen"];
这个解决方案的使用将在更复杂的字符串项目可视化中实现(每个字符串都由对应于另一个数据的 UTF-8 编码值的二进制数字组成)呈方形,特别是从左侧对角线排列顶角。提前致谢!
path
方法,给出给定 [row, col] 的有效对角线路径
diagonals
,从第一列和最后一行开始的聚合路径。
- 根据生成的对角线路径简单
map
洗牌。
PS: 未测试数组长度不是正方形的情况。
const path = (row, col, len, res) => {
while (row > -1 && col < len) {
res.push([row, col]);
row--;
col++;
}
return res;
};
const diagonals = (len) => {
const res = [];
for (let i = 0; i < len; i++) {
path(i, 0, len, res);
}
for (let j = 1; j < len; j++) {
path(len - 1, j, len, res);
}
return res;
};
// const input = [0, 1, 2, 3, 4, 5, 6, 7, 8];
const input = ["dog", "cat", "bear", "wolf", "lynx", "hare", "sheep", "owl", "hen"]
const len = Math.floor(Math.sqrt(input.length));
const output = [...input]
diagonals(len).map(([row, col], i) => output[row * len + col] = input[i]);
console.log(output.join(', '));
我花了一些时间来正确地计算数学,但我能够创建一个函数,其中 returns 一个索引数组以正确的顺序排列:
function getDiagonalArrayIndexes(length) {
const sqrt = Math.floor(Math.sqrt(length));
const formula = (x, y) => (y + x) * (y + x + 1) / 2 + x;
return Array.from({ length: sqrt*sqrt }, (_, i) => {
let x = i % sqrt, y = Math.floor(i / sqrt);
if (x + y < sqrt) {
return formula(x, y);
} else {
return length - 1 - formula(sqrt - 1 - x, sqrt - 1 - y);
}
})
// In case length's square root is not an integer
.concat(new Array(length - sqrt * sqrt).fill(null));
}
printSquare( getDiagonalArrayIndexes(9) );
printSquare( getDiagonalArrayIndexes(16) );
printSquare( getDiagonalArrayIndexes(25) ); /* Just for the demo */ function printSquare(n){const o=Math.sqrt(n.length),t=[];for(var e=0,a=0;e<n.length;e++)e>=o&&e%o==0&&a++,t[a]=t[a]||[],t[a].push(n[e]);console.log("[\n"+t.map(n=>n.map(n=>(" "+n).slice(-3)).join(",")).join(",\n")+"\n]")}document.body.innerHTML="<style>\n .as-console-wrapper { max-height: 100% !important; top: 0; }\n</style>";
然后您可以重复使用它并使用您的数据映射索引:
function reorderDiagonally(arr) {
return getDiagonalArrayIndexes(arr.length)
.map(i => i !== null ? arr[i] : '');
}
var arr = ["dog", "cat", "bear", "wolf", "lynx", "hare", "sheep", "owl", "hen"];
console.log(JSON.stringify( reorderDiagonally(arr) )); /* Just for the demo */ function getDiagonalArrayIndexes(r){const t=Math.floor(Math.sqrt(r)),n=(r,t)=>(t+r)*(t+r+1)/2+r,l=Array.from({length:t*t},(l,a)=>{let e=a%t,o=Math.floor(a/t);return e+o<t?n(e,o):r-1-n(t-1-e,t-1-o)});return l.concat(new Array(r-l.length).fill(null))}
我有一个 字符串数组 ,例如:
var arr=["dog", "cat", "bear", "wolf", "lynx", "hare", "sheep", "owl", "hen"];
要引用这些值中的任何一个,都有从0到8的对应键,即arr[3]对应于“wolf”。实际数组的项目数量可能会有所不同,并且其中有超过 100 个项目。在这个例子中有 9 [0,1,2,3,4,5,6,7,8]
.
我想要完成的是按对角键重新排列项目,即从:
[0,1,2,
3,4,5,
6,7,8]
进入:
[0,2,5,
1,4,7,
3,6,8]
即进入[0,2,5,1,4,7,3,6,8]
,因此也从原来的相应值的序列:
var arr=["dog", "cat", "bear", "wolf", "lynx", "hare", "sheep", "owl", "hen"];
导致重新排列的值:
var arr2=["dog", "bear", "hare", "cat", "lynx", "wolf", "owl", "sheep", "hen"];
这个解决方案的使用将在更复杂的字符串项目可视化中实现(每个字符串都由对应于另一个数据的 UTF-8 编码值的二进制数字组成)呈方形,特别是从左侧对角线排列顶角。提前致谢!
path
方法,给出给定 [row, col] 的有效对角线路径
diagonals
,从第一列和最后一行开始的聚合路径。- 根据生成的对角线路径简单
map
洗牌。
PS: 未测试数组长度不是正方形的情况。
const path = (row, col, len, res) => {
while (row > -1 && col < len) {
res.push([row, col]);
row--;
col++;
}
return res;
};
const diagonals = (len) => {
const res = [];
for (let i = 0; i < len; i++) {
path(i, 0, len, res);
}
for (let j = 1; j < len; j++) {
path(len - 1, j, len, res);
}
return res;
};
// const input = [0, 1, 2, 3, 4, 5, 6, 7, 8];
const input = ["dog", "cat", "bear", "wolf", "lynx", "hare", "sheep", "owl", "hen"]
const len = Math.floor(Math.sqrt(input.length));
const output = [...input]
diagonals(len).map(([row, col], i) => output[row * len + col] = input[i]);
console.log(output.join(', '));
我花了一些时间来正确地计算数学,但我能够创建一个函数,其中 returns 一个索引数组以正确的顺序排列:
function getDiagonalArrayIndexes(length) {
const sqrt = Math.floor(Math.sqrt(length));
const formula = (x, y) => (y + x) * (y + x + 1) / 2 + x;
return Array.from({ length: sqrt*sqrt }, (_, i) => {
let x = i % sqrt, y = Math.floor(i / sqrt);
if (x + y < sqrt) {
return formula(x, y);
} else {
return length - 1 - formula(sqrt - 1 - x, sqrt - 1 - y);
}
})
// In case length's square root is not an integer
.concat(new Array(length - sqrt * sqrt).fill(null));
}
printSquare( getDiagonalArrayIndexes(9) );
printSquare( getDiagonalArrayIndexes(16) );
printSquare( getDiagonalArrayIndexes(25) ); /* Just for the demo */ function printSquare(n){const o=Math.sqrt(n.length),t=[];for(var e=0,a=0;e<n.length;e++)e>=o&&e%o==0&&a++,t[a]=t[a]||[],t[a].push(n[e]);console.log("[\n"+t.map(n=>n.map(n=>(" "+n).slice(-3)).join(",")).join(",\n")+"\n]")}document.body.innerHTML="<style>\n .as-console-wrapper { max-height: 100% !important; top: 0; }\n</style>";
然后您可以重复使用它并使用您的数据映射索引:
function reorderDiagonally(arr) {
return getDiagonalArrayIndexes(arr.length)
.map(i => i !== null ? arr[i] : '');
}
var arr = ["dog", "cat", "bear", "wolf", "lynx", "hare", "sheep", "owl", "hen"];
console.log(JSON.stringify( reorderDiagonally(arr) )); /* Just for the demo */ function getDiagonalArrayIndexes(r){const t=Math.floor(Math.sqrt(r)),n=(r,t)=>(t+r)*(t+r+1)/2+r,l=Array.from({length:t*t},(l,a)=>{let e=a%t,o=Math.floor(a/t);return e+o<t?n(e,o):r-1-n(t-1-e,t-1-o)});return l.concat(new Array(r-l.length).fill(null))}