如果我有一个4x4 2d数组并想处理特定的列,则可以使用映射将其获取并重新设置,也可以获取其浅表副本并直接处理原始数组值。 / p>
获取/设置方式
// create the original array
let arr = [...Array(4)].map(e => Array(4).fill(0))
console.log(arr)
// get a specific column, e.g. the 3d
let myColumn = arr.map(tile => tile[3])
// change it
myColumn[2] = 1
// set it back
arr.map((line, i) => line[3] = myColumn[i])
console.log("modified array", arr)
更新
这是我的(难看的)getter / setter函数,可能非常完善。在每种情况下,它甚至都无法正确进行深度复制(例如,使用index > 11
进行get复制),但仍然可以完成工作。
const getLine = (index) => {
if (index < 4) return field.map(fieldLine => fieldLine[index])
if (index > 3 && index < 8) return field[index - 4].slice().reverse()
if (index > 7 && index < 12) return field.map(fieldLine => fieldLine[Math.abs(index - 11)]).slice().reverse()
if (index > 11) return field.slice()[Math.abs(index - 15)]
}
const setLine = (index, line) => {
if (index < 4) field.map((fieldLine, i) => fieldLine[index] = line[i])
if (index > 3 && index < 8) field[index - 4] = line.reverse()
if (index > 7 && index < 12) field.slice().reverse().map((fieldLine, i) => fieldLine[Math.abs(index - 11)] = line[i])
if (index > 11) field[Math.abs(index - 15)] = line
}
仅供参考,原来的问题在这里:https://www.codewars.com/kata/4-by-4-skyscrapers
答案 0 :(得分:2)
您cannot make a "shallow copy" of primitive values-当您制作arr.map(tile => tile[3])
时,您正在使用 new 值创建一个新数组,因此更改一个不会更改另一个。
但是,您可以创建 objects 的数组,因为对象的值是它们的引用
let grid = [
[{value: 1}, {value: 2}],
[{value: 3}, {value: 4}],
];
//take a column
let col2 = grid.map(row => row[1]);
//change one value
col2[1].value = 42;
//the original changed
console.log(grid);
如果您需要基于列进行频繁的更改,则不需要每次都map(row => row[columnNumber])
,甚至不需要matrix transposition来有效地旋转网格。您可以简单地制作两个 网格-一个代表列,其他代表行。如果首先从“普通”网格开始,将其填充对象,然后对其进行转置,那么您将对同一数据有效地拥有两个视图:
let rows = [
[ {cell: "a1"}, {cell: "a2"}, {cell: "a3"}, {cell: "a4"} ],
[ {cell: "b1"}, {cell: "b2"}, {cell: "b3"}, {cell: "b4"} ],
[ {cell: "c1"}, {cell: "c2"}, {cell: "c3"}, {cell: "c4"} ],
[ {cell: "d1"}, {cell: "d2"}, {cell: "d3"}, {cell: "d4"} ]
];
//transpose
let columns = rows[0].map((col, i) => rows.map(row => row[i]));
//show
console.log("rows:");
console.log(format(rows));
console.log("----");
console.log("columns:");
console.log(format(columns));
console.log("----");
//take a column
let col2 = columns[1];
//update a value
col2[2].cell = "XX";
//show again
console.log("after the change");
console.log("rows:");
console.log(format(rows));
console.log("----");
console.log("columns:");
console.log(format(columns));
console.log("----");
//helper function to display the grids more compactly
function format(arr) {
return arr
.map(arr => arr.map(({cell}) => cell).join())
.join("\n");
}
答案 1 :(得分:1)
如果要进行浅表复制,则必须使用对象而不是原始对象。
然后代码可能像这样:
// filling the array:
/*...*/.fill({value: 0})
// changing the value:
myColumn[2].value = 1
我不知道您的应用程序对资源的敏感程度,但是这样您的内存消耗将在某种程度上增加(取决于应用程序)。
答案 2 :(得分:1)
1。传播算子(浅副本)
numbers = [1, 2, 3];numbersCopy = [...numbers];
注意:这不能安全地复制多维数组。数组/对象值是按引用而不是按值复制的。
这很好
numbersCopy.push(4);
console.log(numbers, numbersCopy);
// [1, 2, 3] and [1, 2, 3, 4]// numbers is left alone
这不好
nestedNumbers = [[1], [2]];numbersCopy = [...nestedNumbers];
2。 Good Old for()循环(浅拷贝)
考虑到功能性编程在我们圈子中的流行程度,我认为这种方法最受欢迎。 纯粹或不纯,声明式或命令式,就可以完成工作!
numbers = [1, 2, 3];numbersCopy = [];
for (i = 0; i < numbers.length; i++) {
numbersCopy[i] = numbers[i];
}
注意:这不能安全地复制多维数组。由于使用的是=运算符,它将通过引用而不是通过值分配对象/数组。
这很好
numbersCopy.push(4);
console.log(numbers, numbersCopy);
// [1, 2, 3] and [1, 2, 3, 4]// numbers is left alone
这不好
nestedNumbers = [[1], [2]];numbersCopy = [];
for (i = 0; i < nestedNumbers.length; i++) {
numbersCopy[i] = nestedNumbers[i];
}
numbersCopy[0].push(300);
console.log(nestedNumbers, numbersCopy);
// [[1, 300], [2]]// [[1, 300], [2]]// They've both been changed because they share references
3。 Array.map(浅副本)
要将数字列表加倍,请使用带有double函数的map。
numbers = [1, 2, 3];
double = (x) => x * 2;
numbers.map(double);
4。 Array.filter(浅拷贝)
此函数返回一个数组,就像map一样,但是不能保证长度相同。
如果要过滤偶数怎么办?
[1, 2, 3].filter((x) => x % 2 === 0)// [2]
输入数组的长度为3,但结果为1。
但是,如果您的过滤器的谓词始终返回true,那么您将得到一个重复项!
numbers = [1, 2, 3];numbersCopy = numbers.filter(() => true);
每个元素都通过了测试,因此可以返回。
注意:这还会通过引用而不是值来分配对象/数组。
5。 Array.reduce(浅副本)
使用reduce克隆数组几乎让我感到难过,因为它的功能要强大得多。但是,我们开始...
numbers = [1, 2, 3];
numbersCopy = numbers.reduce((newArray, element) => {
newArray.push(element);
return newArray;
}, []);
reduce在遍历列表时转换初始值。
此处的初始值是一个空数组,我们将使用每个元素填充它。该数组必须从函数中返回,以便在下一次迭代中使用。
注意:这还会通过引用而不是值来分配对象/数组。
答案 3 :(得分:0)
T