2016-06-27 20 views
13

Làm thế nào các hoạt động sau đây có thể được thực hiện mà không đột biến mảng:Thay thế phần tử ở vị trí cụ thể trong một mảng mà không biến đổi nó

let array = ['item1']; 
console.log(array); // ['item1'] 
array[2] = 'item2'; // array is mutated 
console.log(array); // ['item1', undefined, 'item2'] 

Trong đoạn mã trên, array biến được biến đổi. Làm thế nào tôi có thể thực hiện các hoạt động tương tự mà không đột biến mảng?

+0

Nếu bạn muốn một cái gì đó ** nhanh ** https://stackoverflow.com/a/47943825/1480391,;) –

Trả lời

26

Bạn có thể sử dụng Object.assign:

Object.assign([], array, {2: newItem}); 
+1

@DanPrince Không chắc chắn về cách các cấu trúc chia sẻ này được triển khai. Nhưng slice sao chép toàn bộ mảng sao cho trường hợp đó cũng là O (n). – Oriol

+0

Bất kỳ tài liệu nào về 'Object.assign'? –

+0

Điều đó nói rằng, sao chép một mảng với 'slice' có thể nhanh hơn bởi vì' length' được sao chép trước tiên, do đó, preallocation là có thể. 'Object.assign (array.slice(), {2: newItem});' là một khả năng khác. – Oriol

5

Bạn chỉ có thể thiết lập một một mảng mới như vậy:

const newItemArray = array.slice(); 

Và sau đó thiết lập giá trị cho các chỉ số mà bạn muốn có một giá trị cho.

newItemArray[position] = newItem 

và trả lại điều đó. Các giá trị theo chỉ mục ở giữa sẽ có undefined.

Hoặc thay thế rõ ràng sẽ là:

Object.assign([], array, {<position_here>: newItem}); 
1

var list1 = ['a','b','c']; 
 
var list2 = list1.slice(); 
 
list2.splice(2, 0, "beta", "gamma"); 
 
console.log(list1); 
 
console.log(list2);

Đây có phải là những gì bạn muốn?

4

Vâng, về mặt kỹ thuật, điều này sẽ không được thay thế vì không có mục nào trong chỉ mục bạn đang thay đổi.

Xem cách nó được xử lý trong Clojure — một ngôn ngữ được xây dựng xung quanh việc triển khai chính tắc cho cấu trúc dữ liệu không thay đổi.

(assoc [1] 2 3) 
;; IndexOutOfBoundsException 

Nó không chỉ thất bại mà còn bị lỗi. Các cấu trúc dữ liệu này được thiết kế mạnh mẽ nhất có thể và khi bạn gặp phải các loại lỗi này, thường không phải vì bạn đã phát hiện ra một trường hợp cạnh, nhưng nhiều khả năng bạn đang sử dụng cấu trúc dữ liệu sai.

Nếu bạn kết thúc bằng mảng thưa thớt, hãy xem xét mô hình hóa chúng bằng các đối tượng hoặc bản đồ để thay thế.

let items = { 0: 1 }; 
{ ...items, 2: 3 }; 
// => { 0: 1, 2: 3 } 

let items = new Map([ [0, 1] ]); 
items(2, 3); 
// => Map {0 => 1, 2 => 3} 

Tuy nhiên, Bản đồ là một cấu trúc dữ liệu cơ bản có thể thay đổi, vì vậy bạn sẽ cần phải trao đổi này ra cho một biến thể bất biến với một thư viện như Immutable.js hoặc Mori.

let items = Immutable.Map([ [0, 2] ]); 
items.set(2, 3); 
// => Immutable.Map {0 => 1, 2 => 3} 

let items = mori.hashMap(); 
mori.assoc(items, 2, 3); 
// => mori.hashMap {0 => 1, 2 => 3} 

Tất nhiên, có thể có lý do chính đáng để sử dụng mảng JavaScript, vì vậy đây là giải pháp để đo lường tốt.

function set(arr, index, val) { 
    if(index < arr.length) { 
    return [ 
     ...arr.slice(0, position), 
     val, 
     ...arr.slice(position + 1) 
    ]; 
    } else { 
    return [ 
     ...arr, 
     ...Array(index - arr.length), 
     val 
    ]; 
    } 
} 
0

Dưới đây là cách tôi muốn làm điều đó:

function update(array, newItem, atIndex) { 
    return array.map((item, index) => index === atIndex ? newItem : item); 
} 

Nhìn chung, hoạt động Mảng-lan sản xuất vài mảng tạm thời cho bạn, nhưng map thì không, vì vậy nó có thể nhanh hơn.Bạn cũng có thể nhìn vào this discussion như một tài liệu tham khảo

+0

Rất tốt nhưng thảo luận redux về việc loại bỏ một phần tử, tôi nghĩ cách nhanh nhất để thay thế một phần tử là https://stackoverflow.com/a/47943825/1480391;) –

Các vấn đề liên quan