Javascript ES6 / ES5 tìm trong mảng và thay đổi


133

Tôi có một mảng các đối tượng. Tôi muốn tìm theo một số lĩnh vực, và sau đó thay đổi nó:

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

var foundItem = items.find(x => x.id == item.id);
foundItem = item;

Tôi muốn nó thay đổi đối tượng ban đầu. Làm sao? (Tôi không quan tâm nếu nó cũng sẽ ở trong lodash)


Liều đối tượng mới hơn của bạn itemcó chứa một idkhóa? hoặc bạn có nhớ có id cũng như tất cả các thuộc tính từ itemđối tượng trong mục nhập mảng không?
Koushik Chatterjee

Câu trả lời:


250

Bạn có thể sử dụng find Index để tìm chỉ mục trong mảng của đối tượng và thay thế nó theo yêu cầu:

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

var foundIndex = items.findIndex(x => x.id == item.id);
items[foundIndex] = item;

Điều này giả định ID duy nhất. Nếu ID của bạn được sao chép (như trong ví dụ của bạn), có lẽ tốt hơn nếu bạn sử dụng forEach:

items.forEach((element, index) => {
    if(element.id === item.id) {
        items[index] = item;
    }
});

16
@georg Điều đó sẽ trả về một mảng mới mặc dù.
Mã hóa

3
Hàm => sẽ không hoạt động trong IE11. Gần đây bị cắn bởi điều này.
Lewis Cianci

1
có thể tốt hơn là sử dụng lettừ khóa thay vìvar
Inus Saha

Chỉ cần FYI, điều này không hoạt động trong một số phiên bản của ph PhantomJS
Sid

1
Tôi thích phương thức dài dòng hơn @CodingIntrigue sử dụng thay vì sử dụng một lớp lót mapmà @georg sử dụng. Thể dục dụng cụ ít tinh thần cần thiết để tìm hiểu những gì đang xảy ra. Đáng giá thêm dòng mã.
Joshua Pinter

44

Cách tiếp cận tốt nhất của tôi là:

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

items[items.findIndex(el => el.id === item.id)] = item;

Tham chiếu cho find Index

Và trong trường hợp bạn không muốn thay thế bằng đối tượng mới, nhưng thay vào đó để sao chép các trường của item, bạn có thể sử dụng Object.assign:

Object.assign(items[items.findIndex(el => el.id === item.id)], item)

thay thế cho .map():

Object.assign(items, items.map(el => el.id === item.id? item : el))

Phương pháp chức năng :

Không sửa đổi mảng, sử dụng một mảng mới, do đó bạn không tạo ra tác dụng phụ

const updatedItems = items.map(el => el.id === item.id ? item : el)

1
Vui lòng liên kết đến một trang tiếng Anh nếu câu hỏi ban đầu bằng tiếng Anh. Ngoài ra, ví dụ này giả định đối tượng luôn được tìm thấy.
raarts

1
Bạn luôn có thể gói nó trong một biểu thức thử bắt sau đó ... phải không?
Soldeplata Saketos

1
Và hoàn toàn theo nghĩa đen đối với câu hỏi của bài viết, anh ấy muốn chỉnh sửa một yếu tố trong một mảng. Anh ta không muốn biết nó có tồn tại hay không, vì vậy chúng tôi cho rằng anh ta đã làm điều đó trước đây.
Soldeplata Saketos

@SoldeplataSaketos có, bạn có thể gói nó trong một try/catch, nhưng bạn không nên, vì không tìm thấy phần tử không phải là trường hợp ngoại lệ; đó là trường hợp tiêu chuẩn bạn nên tính đến bằng cách kiểm tra giá trị trả về findIndexvà sau đó chỉ cập nhật mảng khi tìm thấy phần tử.
Wayne

20

Một cách tiếp cận khác là sử dụng mối nối .

Các splice()phương pháp làm thay đổi nội dung của một mảng bằng cách loại bỏ hoặc thay thế các yếu tố hiện hữu và / hoặc thêm các yếu tố mới tại chỗ .

Lưu ý: Trong trường hợp bạn đang làm việc với các khung phản ứng, nó sẽ cập nhật "chế độ xem", mảng của bạn "biết" bạn đã cập nhật nó.

Câu trả lời :

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

let foundIndex = items.findIndex(element => element.id === item.id)
items.splice(foundIndex, 1, item)

Và trong trường hợp bạn chỉ muốn thay đổi giá trị của một mặt hàng, bạn có thể sử dụng chức năng tìm :

// Retrieve item and assign ref to updatedItem
let updatedItem = items.find((element) => { return element.id === item.id })

// Modify object property
updatedItem.aProp = ds.aProp

14

Cho một đối tượng thay đổi và một mảng:

const item = {...}
let items = [{id:2}, {id:3}, {id:4}];

Cập nhật mảng với đối tượng mới bằng cách lặp qua mảng:

items = items.map(x => (x.id === item.id) ? item : x)

Xin đừng chỉ dán mã. Giải thích những gì đang được thực hiện và làm thế nào điều này giải quyết vấn đề.
Spencer

1
Tôi nghĩ rằng đây là giải pháp tốt nhất vì nó có hiệu suất tốt nhất vì nó chỉ đi qua mảng một lần và cũng thay đổi tham chiếu của mảng, vì vậy nó sẽ tránh được các tình huống có thể thay đổi
Ohad Sadan

6

Có thể sử dụng Bộ lọc .

const list = [{id:0}, {id:1}, {id:2}];
let listCopy = [...list];
let filteredDataSource = listCopy.filter((item) => {
       if (item.id === 1) {
           item.id = 12345;
        }

        return item;
    });
console.log(filteredDataSource);

Mảng [Đối tượng {id: 0}, Đối tượng {id: 12345}, Đối tượng {id: 2}]


Tôi thích bộ lọc vì nó cho phép tạo một mảng mới và vì mục này cũng không tồn tại được 'xóa'
pungggi

0

đã làm cho tôi

let returnPayments = [ ...this.payments ];

returnPayments[this.payments.findIndex(x => x.id == this.payment.id)] = this.payment;

1
Xin đừng chỉ dán mã. Giải thích những gì đang được thực hiện và làm thế nào điều này giải quyết vấn đề.
Adrian Mole

Câu trả lời được đánh giá cao nhất được chấp nhận không khác nhau nhiều, nhưng bạn đã không hướng đến họ cập nhật câu trả lời .. tại sao vậy?
li x

0

Trong khi hầu hết các câu trả lời hiện có là tuyệt vời, tôi muốn bao gồm một câu trả lời bằng cách sử dụng vòng lặp for truyền thống, cũng cần được xem xét ở đây. OP yêu cầu một câu trả lời tương thích ES5 / ES6 và vòng lặp for truyền thống được áp dụng :)

Vấn đề với việc sử dụng các hàm mảng trong kịch bản này là chúng không làm biến đổi các đối tượng, nhưng trong trường hợp này, đột biến là một yêu cầu. Hiệu suất đạt được khi sử dụng vòng lặp truyền thống chỉ là phần thưởng (rất lớn).

const findThis = 2;
const items = [{id:1, ...}, {id:2, ...}, {id:3, ...}];

for (let i = 0, l = items.length; i < l; ++i) {
  if (items[i].id === findThis) {
    items[i].iAmChanged = true;
    break;
  }
}

Mặc dù tôi là một fan hâm mộ lớn của các hàm mảng, nhưng đừng để chúng là công cụ duy nhất trong hộp công cụ của bạn. Nếu mục đích là làm thay đổi mảng, chúng không phù hợp nhất.


0

Một lớp lót sử dụng toán tử trải.

 const updatedData = originalData.map(x => (x.id === id ? { ...x, updatedField: 1 } : x));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.