menghapus objek dari array dengan properti objek

148
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

Bagaimana cara menghapus objek dari array dengan mencocokkan properti objek?

Tolong hanya JavaScript asli.

Saya mengalami masalah saat menggunakan sambungan karena panjangnya berkurang dengan setiap penghapusan. Menggunakan clone dan splicing pada orignal index masih menyisakan masalah panjang yang semakin berkurang.

Dan Kanze
sumber
1
Pengulangan ke belakang harus memperbaiki masalah perubahan panjang
Ian
1
Sangat disayangkan bahwa tidak ada cara standar yang tepat untuk menghapus item dari larik objek. Pantas saja ada begitu banyak skrip pihak ketiga. Itu hal yang mendasar.
guitarlass
Kemungkinan duplikat dari Hapus elemen array berdasarkan properti objek
vahdet

Jawaban:

159

Saya berasumsi Anda menggunakan splicesesuatu seperti ini?

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

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

Yang perlu Anda lakukan untuk memperbaiki bug adalah pengurangan iuntuk waktu berikutnya, lalu (dan mengulang ke belakang juga merupakan opsi):

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

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

Untuk menghindari penghapusan waktu linier, Anda dapat menulis elemen array yang ingin Anda simpan di atas array:

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;

dan untuk menghindari pencarian waktu linier dalam runtime modern, Anda dapat menggunakan kumpulan hash:

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;

yang bisa dibungkus dengan fungsi yang bagus:

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

Jika Anda tidak perlu melakukannya di tempat, itu Array#filter:

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

Anda dapat menghapus item dengan salah satu propertinya tanpa menggunakan lib pihak ketiga seperti ini:

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

~removeIndex && array.splice(removeIndex, 1);
parlemen
sumber
1
Ini adalah jawaban yang sangat elegan.
Scott Silvi
hal lain yang saya inginkan, Akan ada tombol terpisah untuk setiap objek dalam array. jika saya ingin menghapus objek tertentu di tombol array yang diklik dan itu harus dipindahkan ke array sekunder lain. Bagaimana cara melakukannya . saya telah menggunakan angular js ng-repeat untuk menghasilkan item. dapatkah Anda membantu saya
Thilak Raj
pendekatan yang sangat bagus dan elegan. pujian! Hanya satu hal yang perlu diperhatikan; jika indeks yang dibutuhkan tidak ditemukan pada larik peta, itu akan mengembalikan -1; dengan demikian sambungan akan menghapus elemen terakhir.
mcy
16
Atau jika Anda bingung dengan tilde pada baris terakhir, Anda mungkin menemukan ini lebih jelas: (removeIndex> = 0) && array.splice (removeIndex, 1);
wojjas
1
@ Parlemen - apakah ada dokumentasi tentang tilde dalam contoh Anda? Saya belum pernah melihat ini sebelumnya.
webdad3
48

Dengan lodash / garis bawah:

Jika Anda ingin memodifikasi array yang sudah ada, maka kita harus menggunakan splice . Berikut adalah cara yang sedikit lebih baik / mudah dibaca menggunakan findWhere dari garis bawah / 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);

Dengan ES5 atau lebih tinggi

( tanpa lodash / garis bawah )

Dengan ES5 dan seterusnya kami memiliki findIndexmetode pada array, jadi mudah tanpa lodash / underscore

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

(ES5 didukung di hampir semua browser morden)

Tentang findIndex , dan kompatibilitas Browsernya

Rahul R.
sumber
bagaimana cara menghapus semua item dalam array objek tetapi saya juga membutuhkan panggilan balik
Muhaimin
apa yang Anda maksud dengan callback juga, Anda dapat menggunakan kode di atas untuk menghapus objek dari array ..
Rahul R.
1
Bagus. Saya akan menambahkan ini ke toolbelt saya
abyrne85
hal lain yang saya inginkan, Akan ada tombol terpisah untuk setiap objek dalam array. jika saya ingin menghapus objek tertentu di tombol array yang diklik dan itu harus dipindahkan ke array sekunder lain. Bagaimana cara melakukannya . saya telah menggunakan angular js ng-repeat untuk menghasilkan item. dapatkah Anda membantu saya
Thilak Raj
4
Suka saran ES5 ini, karena bahkan dapat ditulis dengan cara yang lebih pendekitems.splice(items.findIndex(i => i.id === "abc"), 1)
bramchi
29

findIndex berfungsi untuk browser modern:

var myArr = [{id:'a'},{id:'myid'},{id:'c'}];
var index = myArr.findIndex(function(o){
  return o.id === 'myid';
})
if (index !== -1) myArr.splice(index, 1);
fatlinesofcode
sumber
Saya suka jawaban modern ini, kecuali kode Anda tidak menangkap kasus ketika index = -1
rmcsharry
2
jawaban yang sangat sederhana dibandingkan dengan yang lain dan berfungsi dengan baik.
arun
sederhana namun kuat asnwer
Shelly
16

Untuk menghapus sebuah objek dengan idnya dalam larik yang diberikan;

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

Jika Anda hanya ingin menghapusnya dari array yang ada dan tidak membuat yang baru, coba:

var items = [{Id: 1},{Id: 2},{Id: 3}];
items.splice(_.indexOf(items, _.find(items, function (item) { return item.Id === 2; })), 1);
pengguna2704940
sumber
7
perhatikan bahwa jawaban ini membutuhkan perpustakaan garis bawah
JoshuaDavid
2
Saya tidak akan merekomendasikan ini karena jika elemen tidak ditemukan _.indexOf akan mengembalikan -1 => items.splice (-1,1)
user1441287
6

Ulangi secara terbalik dengan mengurangi iuntuk menghindari masalah:

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

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

Atau gunakan filter:

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

Lihat ini menggunakan Set dan filter ES6.

  let result = arrayOfObjects.filter( el => (-1 == listToDelete.indexOf(el.id)) );
  console.log(result);

Ini JsFiddle: https://jsfiddle.net/jsq0a0p1/1/

Miroslav Savovski
sumber
1
Bekerja dengan sempurna!
Antoni Kepinski
Pendekatan paling modern dan elegan menurut saya.
AC Patrice
4

Tolong hanya JavaScript asli.

Sebagai alternatif, solusi yang lebih "fungsional", bekerja pada ECMAScript 5, Anda dapat menggunakan:

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' } ]

Menurut definisi 'Array.prototype.reduceRight' di ECMA-262 :

reduceRight tidak secara langsung mengubah objek yang dipanggil, tetapi objek tersebut dapat dimutasi oleh panggilan ke callbackfn .

Jadi ini adalah penggunaan yang valid dari reduceRight.

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

sesuai jawaban Anda akan seperti ini. ketika Anda mengklik beberapa objek tertentu, kirim indeks di param untuk fungsi delete me. Kode sederhana ini akan bekerja seperti pesona.

function deleteme(i){
    if (i > -1) {
      arrayOfObjects.splice(i, 1);
    }
}
Subhojit Mondal
sumber
1
Terima kasih ini banyak membantu :)
RAJESH KUMAR ARUMUGAM
1

dengan filter & indexOf

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

dengan filter & termasuk

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

Jika Anda menyukai parameter deskriptif pendek dan mandiri atau jika Anda tidak ingin menggunakan splicedan menggunakan filter langsung atau jika Anda hanyalah orang SQL seperti saya:

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

Dan contoh penggunaan:

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)
Mehmet Kaplan
sumber
0

Anda bisa menggunakan filter. Metode ini selalu mengembalikan elemen jika kondisinya benar. Jadi jika Anda ingin menghapus dengan id Anda harus menyimpan semua elemen yang tidak cocok dengan id yang diberikan. Berikut ini contohnya:

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

David Benitez Riba
sumber