[英]How can I create a shallow copy of an array with a map like function?
如果我有一個 4x4 2d 數組並且想要處理特定列,我可以使用地圖獲取它並將其設置回原處,或者我可以獲得它的淺表副本並直接處理原始數組值。
獲取/設置方式
// create the original array let arr = [...Array(4)].map(e => Array(4).fill(0)) console.log(arr) // get a specific column, eg 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 函數,可能非常完美。 它甚至在每種情況下都沒有正確地進行深度復制(例如 get with index > 11
),但它仍然可以完成這項工作。
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
您不能對原始值進行“淺表復制” -當您創建arr.map(tile => tile[3])
您將在創建具有新值的新數組,因此更改一個不會更改另一個。
但是,您可以創建一個對象數組,因為對象的值是它們的引用
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])
甚至矩陣轉置來有效旋轉網格。 您可以簡單地制作兩個網格-一個代表列,另一列。 如果首先從“普通”網格開始,將其填充對象,然后對其進行轉置,那么您將有效地使用同一數據的兩個視圖:
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"); }
如果要進行淺表復制,則必須使用一個對象,而不是原始對象。
代碼如下:
// filling the array:
/*...*/.fill({value: 0})
// changing the value:
myColumn[2].value = 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轉換初始值。
此處的初始值是一個空數組,我們將使用每個元素填充它。 該數組必須從函數中返回,以在下一次迭代中使用。
注意:這也按引用而不是按值分配對象/數組。
// create the original array let arr = [...Array(4)].map(e => Array(4).fill(0)) console.log(arr) // get copy of arr with changed column const cloneSquareAndChangeColumn = (square, colIndex, newValue) => { return square.map((row, col) => { return [...row.slice(0, colIndex), newValue, ...row.slice(colIndex + 1)]; }); } // test changing last column console.log("cloned and changed arr: \\n", cloneSquareAndChangeColumn(arr, 3, 1));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.