Javascript ES6 / ES5는 배열에서 찾고 변경


133

객체 배열이 있습니다. 일부 필드를 찾아서 변경하고 싶습니다.

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

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

원본 객체를 변경하고 싶습니다. 어떻게? (나는 그것이 lodash에있을지라도 신경 쓰지 않는다)


새로운 물체 itemid키 가 들어 있습니까? 또는 item배열 항목에 객체의 모든 속성뿐만 아니라 ID가 있습니까?
Koushik Chatterjee

답변:


251

findIndex 를 사용 하여 객체 배열에서 색인을 찾아 필요에 따라 바꿀 수 있습니다.

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

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

이것은 고유 ID를 가정합니다. ID가 중복되면 (예와 같이) forEach를 사용하는 것이 좋습니다.

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

16
@georg 그래도 새로운 배열을 반환합니다.
CodingIntrigue

3
IE11에서는 => 기능이 작동하지 않습니다. 최근에 물린.
Lewis Cianci

1
let대신 키워드 를 사용하는 것이 좋습니다.var
Inus Saha

참고로, 일부 버전의 phantomJS
Sid

1
@georg가 사용하는 하나의 라이너 map를 사용하는 대신 @CodingIntrigue가 사용하는 더 자세한 방법을 선호 합니다. 무슨 일이 일어나고 있는지 알아내는 데 필요한 정신 체조가 적습니다. 여분의 코드 줄이 가치가 있습니다.
Joshua Pinter

44

최선의 방법은 다음과 같습니다.

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

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

findIndex에 대한 참조

그리고 새 객체로 바꾸고 싶지 않고 대신 필드를 복사하려면 item다음을 사용할 수 있습니다 Object.assign.

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

대안으로 .map():

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

기능적 접근 :

배열을 수정하지 말고 새 배열을 사용하여 부작용을 일으키지 마십시오.

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

1
원래 질문이 영어 인 경우 영어 페이지에 링크하십시오. 또한이 예에서는 객체가 항상 있다고 가정합니다.
raarts

1
당신은 항상 시도 캐치 표현으로 그것을 감쌀 수 있습니다 ... 맞습니까?
Soldeplata Saketos

1
그리고 그는 게시물의 질문에 완전히 문자 그대로 배열의 요소를 편집하려고합니다. 그는 그것이 존재하는지 아닌지를 알고 싶지 않기 때문에 우리는 그가 이미 그렇게했다고 가정합니다.
Soldeplata Saketos

@SoldeplataSaketos 그렇습니다.을 래핑 할 try/catch있지만 요소를 찾지 못하면 예외가 아닙니다. 반환 값을 확인한 findIndex다음 요소를 찾을 때만 배열을 업데이트하여 고려해야하는 표준 사례 입니다.
웨인

20

다른 방법은 splice 를 사용하는 것 입니다.

splice()방법은 기존 요소를 제거 또는 교체하거나 새 요소 추가하여 배열의 내용을 변경합니다 .

NB : 반응 형 프레임 워크로 작업하는 경우 업데이트 한 "알고있는" "뷰"가 업데이트됩니다.

대답 :

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

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

항목의 값만 변경하려는 경우 찾기 기능을 사용할 있습니다.

// 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

변경된 객체와 배열이 주어지면 :

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

배열을 반복하여 새 객체로 배열을 업데이트하십시오.

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

코드를 붙여 넣지 마십시오. 수행중인 작업과 문제 해결 방법을 설명하십시오.
스펜서

1
배열을 한 번만 통과하고 배열의 참조를 변경하기 때문에 이것이 최상의 성능을 가지므로 이것이 최선의 해결책이라고 생각합니다. 따라서 변경 가능한 상황을 피할 것입니다.
Ohad Sadan

6

Filter를 사용할 수 있습니다 .

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);

배열 [개체 {id : 0}, 개체 {id : 12345}, 개체 {id : 2}]


나는 그것이 새로운 배열을 만들 수 있기 때문에 필터를 좋아하고 이것도 존재하지 않는 항목은 '삭제되었습니다'
pungggi

0

나를 위해 일했다

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

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

1
코드를 붙여 넣지 마십시오. 수행중인 작업과 문제 해결 방법을 설명하십시오.
Adrian Mole

가장 많이 찬성 된 답변은 크게 다르지 않지만 답변을 업데이트하는 것에 대해서는 언급하지 않았습니다. 왜 그런가요?
li x

0

기존 답변의 대부분이 훌륭하지만 전통적인 for 루프를 사용하여 답변을 포함하고 싶습니다. 여기에서도 고려해야합니다. OP는 ES5 / ES6와 호환되는 답변을 요청하고 전통적인 for 루프가 적용됩니다. :)

이 시나리오에서 배열 함수를 사용할 때의 문제는 객체를 돌연변이시키지 않지만이 경우 돌연변이가 필요하다는 것입니다. 전통적인 for 루프를 사용하면 성능이 크게 향상됩니다.

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;
  }
}

나는 배열 함수에 대한 열렬한 팬이지만 도구 상자의 유일한 도구로 사용하지 마십시오. 목적이 배열을 변경하는 경우 가장 적합하지 않습니다.


0

스프레드 연산자를 사용한 원 라이너.

 const updatedData = originalData.map(x => (x.id === id ? { ...x, updatedField: 1 } : x));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.