객체 속성으로 배열에서 객체 제거


138
var listToDelete = ['abc', 'efg'];

var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
                      {id:'efg',name:'em'}, // delete me
                      {id:'hij',name:'ge'}] // all that should remain

객체 속성을 일치시켜 배열에서 객체를 제거하려면 어떻게합니까?

기본 JavaScript 만 사용하십시오.

삭제 할 때마다 길이가 줄어들 기 때문에 스플 라이스를 사용하는 데 문제가 있습니다. Orignal 인덱스에서 복제 및 스 플라이 싱을 사용하면 여전히 길이가 줄어드는 문제가 있습니다.


1
뒤로 반복하면 길이 변화 문제를 해결해야합니다
Ian

1
객체 배열에서 항목을 제거하는 표준 적절한 방법이 없다는 것은 부끄러운 일입니다. 타사 스크립트가 너무 많은 것도 당연합니다. 기본적인 것입니다.
guitarlass

답변:


155

나는 당신 splice이 이와 같은 것을 사용 했다고 가정 합니까?

for (var i = 0; i < arrayOfObjects.length; i++) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
    }
}

버그를 수정하기 위해해야 ​​할 일은 i다음에 줄어드는 것입니다.

for (var i = 0; i < arrayOfObjects.length; i++) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
        i--;
    }
}

선형 시간 삭제를 피하기 위해 배열 위에 유지 하려는 배열 요소를 작성할 수 있습니다 .

var end = 0;

for (var i = 0; i < arrayOfObjects.length; i++) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) === -1) {
        arrayOfObjects[end++] = obj;
    }
}

arrayOfObjects.length = end;

최신 런타임에서 선형 시간 조회를 피하기 위해 해시 세트를 사용할 수 있습니다.

const setToDelete = new Set(listToDelete);
let end = 0;

for (let i = 0; i < arrayOfObjects.length; i++) {
    const obj = arrayOfObjects[i];

    if (setToDelete.has(obj.id)) {
        arrayOfObjects[end++] = obj;
    }
}

arrayOfObjects.length = end;

좋은 기능으로 싸일 수 있습니다.

const filterInPlace = (array, predicate) => {
    let end = 0;

    for (let i = 0; i < array.length; i++) {
        const obj = array[i];

        if (predicate(obj)) {
            array[end++] = obj;
        }
    }

    array.length = end;
};

const toDelete = new Set(['abc', 'efg']);

const arrayOfObjects = [{id: 'abc', name: 'oh'},
                        {id: 'efg', name: 'em'},
                        {id: 'hij', name: 'ge'}];

filterInPlace(arrayOfObjects, obj => !toDelete.has(obj.id));
console.log(arrayOfObjects);

당신이 그 자리에 그것을 할 필요가 없다면, 그것은 Array#filter:

const toDelete = new Set(['abc', 'efg']);
const newArray = arrayOfObjects.filter(obj => !toDelete.has(obj.id));

79

다음과 같은 타사 라이브러리를 사용하지 않고 속성 중 하나를 사용하여 항목을 제거 할 수 있습니다.

var removeIndex = array.map(item => item.id)
                       .indexOf("abc");

~removeIndex && array.splice(removeIndex, 1);

1
이것은 정말 우아한 답변입니다.
Scott Silvi

내가 원하는 또 다른 것은 배열의 모든 객체에 대해 별도의 버튼이있을 것입니다. 배열 버튼에서 특정 객체를 삭제하려면 다른 보조 배열로 이동해야합니다. 그것을하는 방법. angular js ng-repeat를 사용하여 항목을 생성했습니다. 도와주세요
Thilak Raj

아주 훌륭하고 우아한 접근. 명성! 한가지주의 할 점; 맵 배열에서 필요한 인덱스를 찾지 못하면 -1을 리턴합니다. 따라서 접속은 마지막 요소를 제거합니다.
mcy

15
또는 마지막 줄의 물결표로 인해 혼란 스러우면 더 명확하게 찾을 수 있습니다. (removeIndex> = 0) && array.splice (removeIndex, 1);
wojjas

1
@parliament-예제에 물결표에 대한 문서가 있습니까? 나는 이것을 전에 본 적이 없다.
webdad3

43

lodash / 밑줄로 :

기존 배열 자체를 수정하려면 splice 를 사용해야 합니다. 다음은 findWhere of underscore / lodash를 사용하는 조금 더 좋고 읽기 쉬운 방법입니다 .

var items= [{id:'abc',name:'oh'}, // delete me
                  {id:'efg',name:'em'},
                  {id:'hij',name:'ge'}];

items.splice(_.indexOf(items, _.findWhere(items, { id : "abc"})), 1);

ES5 이상

( lodash / 밑줄없이 )

ES5부터는 findIndex배열에 메소드가 있으므로 lodash / underscore없이 쉽게 사용할 수 있습니다.

items.splice(items.findIndex(function(i){
    return i.id === "abc";
}), 1);

(ES5는 거의 모든 morden 브라우저에서 지원됩니다)

findIndex 브라우저 호환성


객체 배열에서 모든 항목을 제거하는 방법은 있지만 콜백도 필요합니다
Muhaimin

콜백의 의미는 무엇입니까? 위의 코드를 사용하여 배열에서 객체를 제거 할 수 있습니다.
Rahul R.

1
좋은데 나는 이것을 내 toolbelt에 추가 할 것이다
abyrne85

내가 원하는 또 다른 것은 배열의 모든 객체에 대해 별도의 버튼이있을 것입니다. 배열 버튼에서 특정 객체를 삭제하려면 다른 보조 배열로 이동해야합니다. 그것을하는 방법. angular js ng-repeat를 사용하여 항목을 생성했습니다. 도와주세요
Thilak Raj

1
더 짧은 방법으로도 작성 될 수 items.splice(items.findIndex(i => i.id === "abc"), 1)
있으므로이

27

findIndex는 최신 브라우저에서 작동합니다.

var myArr = [{id:'a'},{id:'myid'},{id:'c'}];
var index = arr.findIndex(function(o){
     return o.id === 'myid';
})
if (index !== -1) myArr.splice(index, 1);

index = -1 인 경우를 제외하고는 코드가 일치하지 않는다는 점을 제외 하고는이 현대적인 답변이 마음에
들었습니다.

2
다른 사람들에 비해 매우 간단한 대답이며 잘 작동합니다.
arun

간단하면서도 강력한 asnwer
Shelly

15

주어진 배열에서 ID로 객체를 삭제합니다.

const hero = [{'id' : 1, 'name' : 'hero1'}, {'id': 2, 'name' : 'hero2'}];
//remove hero1
const updatedHero = hero.filter(item => item.id !== 1);

10

기존 배열에서 제거하고 새 배열을 만들지 않으려면 다음을 시도하십시오.

var items = [{Id: 1},{Id: 2},{Id: 3}];
items.splice(_.indexOf(items, _.find(items, function (item) { return item.Id === 2; })), 1);

7
이 답변에는 밑줄 라이브러리 가 필요합니다
JoshuaDavid

2
요소가 발견되지 않는 경우 _.indexOf 반환하기 때문에 나는 이것을 권하고 싶지 않다 -1 => items.splice (-1,1)
user1441287

6

i문제점을 피하기 위해 감소 시켜서 역순으로 반복 하십시오.

for (var i = arrayOfObjects.length - 1; i >= 0; i--) {
    var obj = arrayOfObjects[i];

    if (listToDelete.indexOf(obj.id) !== -1) {
        arrayOfObjects.splice(i, 1);
    }
}

또는 사용 filter:

var newArray = arrayOfObjects.filter(function(obj) {
    return listToDelete.indexOf(obj.id) === -1;
});


4

기본 JavaScript 만 사용하십시오.

ECMAScript 5에서 작업하는보다 "기능적인"대안으로 다음을 사용할 수 있습니다.

var listToDelete = ['abc', 'efg'];
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
                      {id:'efg',name:'em'}, // delete me
                      {id:'hij',name:'ge'}]; // all that should remain

arrayOfObjects.reduceRight(function(acc, obj, idx) {
    if (listToDelete.indexOf(obj.id) > -1)
        arrayOfObjects.splice(idx,1);
}, 0); // initial value set to avoid issues with the first item and
       // when the array is empty.

console.log(arrayOfObjects);
[ { id: 'hij', name: 'ge' } ]

ECMA-262에서 'Array.prototype.reduceRight'의 정의에 따르면 :

reduceRight는 호출 된 객체를 직접 변경하지 않지만 callbackfn 호출로 인해 객체가 변경 될 수 있습니다 .

따라서 유효한 사용법입니다 reduceRight.


2
var arrayOfObjects = [{id:'abc',name:'oh'}, // delete me
                      {id:'efg',name:'em'}, // delete me
                      {id:'hij',name:'ge'}] // all that should remain

귀하의 답변에 따라이 같은 것입니다. 특정 객체를 클릭하면 매개 변수에서 색인을 보내 삭제 기능을 보내십시오. 이 간단한 코드는 매력처럼 작동합니다.

function deleteme(i){
    if (i > -1) {
      arrayOfObjects.splice(i, 1);
    }
}

1
이것은 부지 :) 도움이 Thnaks
라 제쉬 쿠마르 ARUMUGAM

1

필터 및 indexOf

withLodash = _.filter(arrayOfObjects, (obj) => (listToDelete.indexOf(obj.id) === -1));
withoutLodash = arrayOfObjects.filter(obj => listToDelete.indexOf(obj.id) === -1);

필터 포함 및 포함

withLodash = _.filter(arrayOfObjects, (obj) => (!listToDelete.includes(obj.id)))
withoutLodash = arrayOfObjects.filter(obj => !listToDelete.includes(obj.id));

0

짧고 자기 설명적인 매개 변수를 좋아하거나 splice직접 필터 를 사용 하고 싶지 않거나 단순히 나와 같은 SQL 사람 인 경우 :

function removeFromArrayOfHash(p_array_of_hash, p_key, p_value_to_remove){
    return p_array_of_hash.filter((l_cur_row) => {return l_cur_row[p_key] != p_value_to_remove});
}

그리고 샘플 사용법 :

l_test_arr = 
[
    {
         post_id: 1,
        post_content: "Hey I am the first hash with id 1"
    },
    {
        post_id: 2,
        post_content: "This is item 2"
    },
    {
        post_id: 1,
        post_content: "And I am the second hash with id 1"
    },
    {
        post_id: 3,
        post_content: "This is item 3"
    },
 ];



 l_test_arr = removeFromArrayOfHash(l_test_arr, "post_id", 2); // gives both of the post_id 1 hashes and the post_id 3
 l_test_arr = removeFromArrayOfHash(l_test_arr, "post_id", 1); // gives only post_id 3 (since 1 was removed in previous line)

-1

사용할 수 있습니다 filter. 조건이 true 인 경우이 메소드는 항상 요소를 리턴합니다. 따라서 id로 제거하려면 주어진 id와 일치하지 않는 모든 요소를 ​​유지해야합니다. 예를 들면 다음과 같습니다.

arrayOfObjects = arrayOfObjects.filter (obj => obj.id! = idToRemove)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.