Hapus duplikat dari array objek dalam JavaScript

374

Saya memiliki objek yang berisi array objek.

things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});

Saya bertanya-tanya apa metode terbaik untuk menghapus objek duplikat dari array. Jadi misalnya, segalanya akan menjadi ...

{place:"here",name:"stuff"},
{place:"there",name:"morestuff"}
Travis
sumber
Apakah maksud Anda bagaimana Anda menghentikan hashtable / objek dengan semua parameter yang sama ditambahkan ke array?
Matthew Lock
1
Mathew -> Jika lebih mudah untuk mencegah duplikat objek ditambahkan ke array di tempat pertama, daripada menyaringnya nanti, ya, itu akan baik-baik saja juga.
Travis
2
Terus mengejutkan saya bagaimana orang memberi nama variabel mereka. Kadang-kadang saya pikir mereka benar-benar ingin membuatnya menjadi rumit. Selanjutnya untuk melihat kehendak aaaaa.aaaa.push(...):)
dazito

Jawaban:

154

Metode primitif adalah:

var obj = {};

for ( var i=0, len=things.thing.length; i < len; i++ )
    obj[things.thing[i]['place']] = things.thing[i];

things.thing = new Array();
for ( var key in obj )
    things.thing.push(obj[key]);
aefxx
sumber
15
Anda seharusnya tidak pernah menggunakan panjang dalam loop untuk, karena itu akan memperlambat semuanya menghitungnya pada setiap iterasi. Tetapkan ke variabel di luar loop dan meneruskan variabel, bukan hal-hal.
0v3rth3d4wn
12
@ aefxx Saya tidak begitu mengerti fungsi ini, bagaimana Anda menangani situasi bahwa "tempat" sama tetapi namanya berbeda, haruskah itu dianggap dup atau tidak?
Kuan
2
Meskipun ini berfungsi, itu tidak menangani array yang diurutkan karena mengambil kunci tidak pernah dijamin pesanan. Jadi, Anda akhirnya menyortirnya lagi. Sekarang, misalkan array tidak diurutkan tetapi urutannya penting, tidak ada cara Anda dapat memastikan bahwa pesanan tetap utuh
Deepak GM
1
@DeepakGM Kamu benar sekali. Jawabannya tidak akan (tentu) mempertahankan perintah yang diberikan. Jika itu merupakan persyaratan, seseorang harus mencari solusi lain.
aefxx
Bagaimana saya bisa memodifikasi di atas untuk menghapus objek dari array yang berisi X dan juga de-duped?
Ryan Holton
435

Bagaimana dengan es6sihir?

things.thing = things.thing.filter((thing, index, self) =>
  index === self.findIndex((t) => (
    t.place === thing.place && t.name === thing.name
  ))
)

URL referensi

Solusi yang lebih umum adalah:

const uniqueArray = things.thing.filter((thing, index) => {
  const _thing = JSON.stringify(thing);
  return index === things.thing.findIndex(obj => {
    return JSON.stringify(obj) === _thing;
  });
});

Contoh Stackblitz

Eydrian
sumber
81
Ini dapat disingkat menjadi:things.thing = things.thing.filter((thing, index, self) => self.findIndex(t => t.place === thing.place && t.name === thing.name) === index)
Josh Cole
Bekerja dengan sempurna! var uniqueArrayOfObjects = arrayOfObjects.filter (fungsi (objek, indeks, diri) {indeks balik === self.findIndex (fungsi (t) {return t ['objek-properti'] === objek ['objek-properti'] });}); Pastikan Anda menggunakan sintaks JS yang tepat.
Mohamed Salem Lamiri
Itu adalah sintaks JS yang tepat. Milik Anda tidak menggunakan 1) fungsi panah gemuk 2) pengembalian implisit atau 3) notasi titik. Milik Anda adalah sintaks ES5. Yang lain kebanyakan ES6 (ECMA2015). Semuanya valid pada 2017. Lihat komentar jaredwilli.
agm1984
8
@vsync hanya mengambil jawaban @ BKM dan menyatukannya, solusi generik adalah: const uniqueArray = arrayOfObjects.filter((object,index) => index === arrayOfObjects.findIndex(obj => JSON.stringify(obj) === JSON.stringify(object))); jsfiddle.net/x9ku0p7L/28
Eydrian
9
Kuncinya di sini adalah bahwa metode findIndex () mengembalikan indeks elemen pertama , jadi jika ada elemen kedua yang cocok, itu tidak akan pernah ditemukan dan ditambahkan selama filter. Saya sedang menatapnya sebentar :)
JBaczuk
111

Jika Anda dapat menggunakan pustaka Javascript seperti garis bawah atau lodash, saya sarankan melihat _.uniqfungsi di pustaka mereka. Dari lodash:

_.uniq(array, [isSorted=false], [callback=_.identity], [thisArg])

Pada dasarnya, Anda meneruskan dalam array yang di sini adalah objek literal dan Anda meneruskan atribut yang ingin Anda hapus duplikat dengan dalam array data asli, seperti ini:

var data = [{'name': 'Amir', 'surname': 'Rahnama'}, {'name': 'Amir', 'surname': 'Stevens'}];
var non_duplidated_data = _.uniq(data, 'name'); 

UPDATE : Lodash sekarang telah memperkenalkan .uniqByjuga.

ambodi
sumber
3
@Praveen Pds: Apakah saya mengatakan sesuatu tentang garis bawah pada contoh kode? Saya mengatakan 'lodash' memiliki fungsi ini dan garis bawah memiliki yang serupa. Sebelum memilih, harap baca jawaban dengan cermat.
ambodi
// Mencantumkan objek unik menggunakan _underscore.js holdingObject = _.uniq (holdingObject, fungsi (item, kunci, nama) {return item.name;});
praveenpds
26
Catatan: Anda sekarang harus menggunakan uniqByalih-alih uniq, misalnya _.uniqBy(data, 'name')... dokumentasi: lodash.com/docs#uniqBy
drmrbrewer
83

Saya memiliki persyaratan yang sama persis ini, untuk menghapus objek duplikat dalam array, berdasarkan duplikat pada satu bidang. Saya menemukan kode di sini: Javascript: Hapus Duplikat dari Array Objek

Jadi dalam contoh saya, saya menghapus objek apa pun dari array yang memiliki nilai string licenseNum duplikat.

var arrayWithDuplicates = [
    {"type":"LICENSE", "licenseNum": "12345", state:"NV"},
    {"type":"LICENSE", "licenseNum": "A7846", state:"CA"},
    {"type":"LICENSE", "licenseNum": "12345", state:"OR"},
    {"type":"LICENSE", "licenseNum": "10849", state:"CA"},
    {"type":"LICENSE", "licenseNum": "B7037", state:"WA"},
    {"type":"LICENSE", "licenseNum": "12345", state:"NM"}
];

function removeDuplicates(originalArray, prop) {
     var newArray = [];
     var lookupObject  = {};

     for(var i in originalArray) {
        lookupObject[originalArray[i][prop]] = originalArray[i];
     }

     for(i in lookupObject) {
         newArray.push(lookupObject[i]);
     }
      return newArray;
 }

var uniqueArray = removeDuplicates(arrayWithDuplicates, "licenseNum");
console.log("uniqueArray is: " + JSON.stringify(uniqueArray));

Hasil:

uniqueArray adalah:

[{"type":"LICENSE","licenseNum":"10849","state":"CA"},
{"type":"LICENSE","licenseNum":"12345","state":"NM"},
{"type":"LICENSE","licenseNum":"A7846","state":"CA"},
{"type":"LICENSE","licenseNum":"B7037","state":"WA"}]
James Drinkard
sumber
1
Ini akan lebih bermanfaat jika fungsinya juga dapat memfilter objek 'falsy'. for(var i in array) { if(array[i][prop]){ //valid lookupObject[array[i][prop]] = array[i]; } else { console.log('falsy object'); } }
Abdul Sadik Yalcin
Mengapa tidak meruntuhkan kompleksitas 0 (n) dengan menggunakan: for (let i in originalArray) { if (lookupObject[originalArray[i]['id']] === undefined) { newArray.push(originalArray[i]); } lookupObject[originalArray[i]['id']] = originalArray[i]; }
Tudor B.
ini adalah cara terbaik karena penting untuk mengetahui apa yang Anda inginkan agar tidak diduplikasi. Sekarang dapatkah ini dilakukan melalui peredam untuk standar e6?
Christian Matthew
70

Satu liner terpendek untuk ES6 +

Temukan unik iddalam array.

arr.filter((v,i,a)=>a.findIndex(t=>(t.id === v.id))===i)

Unik oleh beberapa properti ( placedan name)

arr.filter((v,i,a)=>a.findIndex(t=>(t.place === v.place && t.name===v.name))===i)

Unik oleh semua properti (Ini akan lambat untuk array besar)

arr.filter((v,i,a)=>a.findIndex(t=>(JSON.stringify(t) === JSON.stringify(v)))===i)

Pertahankan kejadian terakhir.

arr.slice().reverse().filter((v,i,a)=>a.findIndex(t=>(t.id === v.id))===i).reverse()
ayam
sumber
2
Magic, ini jawaban yang benar
Luis Contreras
48

Satu liner menggunakan Set

var things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});

// assign things.thing to myData for brevity
var myData = things.thing;

things.thing = Array.from(new Set(myData.map(JSON.stringify))).map(JSON.parse);

console.log(things.thing)

Penjelasan:

  1. new Set(myData.map(JSON.stringify))menciptakan Set objek menggunakan elemen myData stringified.
  2. Tetapkan objek akan memastikan bahwa setiap elemen unik.
  3. Lalu saya membuat array berdasarkan elemen set yang dibuat menggunakan Array.from.
  4. Akhirnya, saya menggunakan JSON.parse untuk mengubah elemen yang dirubah kembali menjadi sebuah objek.
Mμ.
sumber
18
masalahnya adalah {a: 1, b: 2} tidak akan sama dengan {b: 2, a: 1}
PirateApp
2
perlu diingat bahwa akan ada masalah dengan properti Date
MarkosyanArtur
Baris ini menciptakan nilai null acak dengan objek baris yang tidak ada dalam array objek asli. Bisakah Anda membantu?
B1K
47

Menggunakan ES6 + dalam satu baris Anda bisa mendapatkan daftar objek unik dengan kunci:

const unique = [...new Map(arr.map(item => [item[key], item])).values()]

Itu dapat dimasukkan ke dalam fungsi:

function getUniqueListBy(arr, key) {
    return [...new Map(arr.map(item => [item[key], item])).values()]
}

Berikut ini contoh kerjanya:

const arr = [
    {place: "here",  name: "x", other: "other stuff1" },
    {place: "there", name: "x", other: "other stuff2" },
    {place: "here",  name: "y", other: "other stuff4" },
    {place: "here",  name: "z", other: "other stuff5" }
]

function getUniqueListBy(arr, key) {
    return [...new Map(arr.map(item => [item[key], item])).values()]
}

const arr1 = getUniqueListBy(arr, 'place')

console.log("Unique by place")
console.log(JSON.stringify(arr1))

console.log("\nUnique by name")
const arr2 = getUniqueListBy(arr, 'name')

console.log(JSON.stringify(arr2))

bagaimana cara kerjanya

Pertama array ini dipetakan ulang sedemikian rupa sehingga dapat digunakan sebagai input untuk Peta.

arr.map (item => [item [key], item]);

yang berarti setiap item array akan ditransformasikan dalam array lain dengan 2 elemen; tombol yang dipilih sebagai elemen pertama dan seluruh item awal sebagai elemen kedua, ini disebut entri (mis. entri array , entri peta ). Dan sini adalah dokumen resmi dengan contoh yang menunjukkan cara menambahkan entri array di konstruktor Peta.

Contoh ketika kunci ditempatkan :

[["here", {place: "here",  name: "x", other: "other stuff1" }], ...]

Kedua, kami meneruskan array yang dimodifikasi ini ke konstruktor Peta dan inilah keajaiban yang terjadi. Peta akan menghilangkan nilai kunci duplikat, menjaga hanya nilai yang dimasukkan terakhir dari kunci yang sama. Catatan : Peta menjaga urutan penyisipan. ( periksa perbedaan antara Peta dan objek )

Peta baru (array entri baru saja dipetakan di atas)

Ketiga, kami menggunakan nilai peta untuk mengambil item asli, tapi kali ini tanpa duplikat.

Peta baru (mappedArr) .nilai ()

Dan yang terakhir adalah menambahkan nilai-nilai itu ke dalam array baru yang baru sehingga dapat terlihat sebagai struktur awal dan mengembalikannya:

return [... Map baru (mappedArr) .values ​​()]

V. Sambor
sumber
Ini tidak menjawab pertanyaan awal karena ini mencari id. Pertanyaan ini membutuhkan seluruh objek menjadi unik di semua bidang seperti placedanname
L. Holanda
Fungsi ES6 Anda tampak sangat ringkas dan praktis. Bisakah Anda jelaskan lebih banyak? Apa yang sebenarnya terjadi? Apakah duplikat pertama atau terakhir dihapus? Atau itu acak, duplikat mana yang dihapus? Itu akan sangat membantu, terima kasih.
David Schumann
Sejauh yang saya tahu, Peta dengan nilai properti saat kunci dibuat. Tetapi ini bukan 100% bagaimana atau jika susunan array dipertahankan.
David Schumann
1
Hai @ DavidSchumann, saya akan memperbarui jawabannya dan akan menjelaskan cara kerjanya. Tetapi untuk jawaban singkat urutannya dipertahankan dan yang pertama dihapus ... Pikirkan saja bagaimana ia dimasukkan ke dalam peta ... ia memeriksa apakah kunci yang sudah ada itu akan memperbaruinya, maka yang terakhir akan tetap ada
V Sambor
30

Berikut opsi lain untuk melakukannya menggunakan metode pengulangan Array jika Anda hanya perlu membandingkan dengan satu bidang objek:

    function uniq(a, param){
        return a.filter(function(item, pos, array){
            return array.map(function(mapItem){ return mapItem[param]; }).indexOf(item[param]) === pos;
        })
    }

    uniq(things.thing, 'place');
Alex Kobylinski
sumber
Meskipun ini memiliki pesanan lebih besar dari O (n²), ini cocok dengan kasus penggunaan saya karena ukuran array saya akan selalu kurang dari 30. Terima kasih!
Sterex
24

satu liner ada di sini

let arr = [
  {id:1,name:"sravan ganji"},
  {id:2,name:"anu"},
  {id:4,name:"mammu"},
  {id:3,name:"sanju"},
  {id:3,name:"ram"},
];

console.log(Object.values(arr.reduce((acc,cur)=>Object.assign(acc,{[cur.id]:cur}),{})))

sravan ganji
sumber
1
Bagus dan bersih jika Anda hanya ingin menghapus objek dengan nilai duplikat tunggal, tidak begitu bersih untuk objek yang sepenuhnya terduplikasi.
David Barker
22

Jika Anda bisa menunggu untuk menghilangkan duplikat sampai setelah semua penambahan, pendekatan khasnya adalah mengurutkan array terlebih dahulu dan kemudian menghilangkan duplikat. Penyortiran menghindari pendekatan N * N memindai array untuk setiap elemen saat Anda berjalan melalui mereka.

The "menghilangkan duplikasi" fungsi biasanya disebut unik atau uniq . Beberapa implementasi yang ada dapat menggabungkan dua langkah, misalnya, uniq prototipe

Posting ini memiliki beberapa ide untuk dicoba (dan beberapa untuk menghindari :-)) jika perpustakaan Anda belum memilikinya ! Secara pribadi saya menemukan ini yang paling mudah:

    function unique(a){
        a.sort();
        for(var i = 1; i < a.length; ){
            if(a[i-1] == a[i]){
                a.splice(i, 1);
            } else {
                i++;
            }
        }
        return a;
    }  

    // Provide your own comparison
    function unique(a, compareFunc){
        a.sort( compareFunc );
        for(var i = 1; i < a.length; ){
            if( compareFunc(a[i-1], a[i]) === 0){
                a.splice(i, 1);
            } else {
                i++;
            }
        }
        return a;
    }
maccullt
sumber
Itu tidak akan berfungsi untuk objek generik tanpa urutan pengurutan alami.
Tim Down
Benar, saya menambahkan versi perbandingan yang disediakan pengguna.
maccullt
Versi perbandingan yang disediakan pengguna Anda tidak akan berfungsi karena jika fungsi perbandingan Anda function(_a,_b){return _a.a===_b.a && _a.b===_b.b;}maka array tidak akan diurutkan.
graham.reeds
1
Itu adalah fungsi perbandingan yang tidak valid. Dari developer.mozilla.org/en/Core_JavaScript_1.5_Reference/ ... ... bandingkan fungsi (a, b) {if (a kurang dari b oleh beberapa kriteria pemesanan) return -1; jika (a lebih besar dari b oleh kriteria pemesanan) mengembalikan 1; // a harus sama dengan b return 0; } ...
maccullt
22

Cara paling sederhana adalah menggunakan filter:

var uniq = {}
var arr  = [{"id":"1"},{"id":"1"},{"id":"2"}]
var arrFiltered = arr.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true));
console.log('arrFiltered', arrFiltered)

aflex dykyі
sumber
6
Ini praktik yang baik di Stack Overflow untuk menambahkan penjelasan mengapa solusi Anda harus bekerja, terutama bagaimana solusi Anda lebih baik daripada jawaban lainnya. Untuk informasi lebih lanjut baca Cara Menjawab .
Samuel Liew
Ini tidak menjawab pertanyaan awal karena ini mencari id. Pertanyaan ini membutuhkan seluruh objek menjadi unik di semua bidang seperti placedanname
L. Holanda
17

Ini adalah cara umum untuk melakukan ini: Anda meneruskan fungsi yang menguji apakah dua elemen array dianggap sama. Dalam hal ini, ia membandingkan nilai-nilai namedan placeproperti dari dua objek yang dibandingkan.

Jawaban ES5

function removeDuplicates(arr, equals) {
    var originalArr = arr.slice(0);
    var i, len, val;
    arr.length = 0;

    for (i = 0, len = originalArr.length; i < len; ++i) {
        val = originalArr[i];
        if (!arr.some(function(item) { return equals(item, val); })) {
            arr.push(val);
        }
    }
}

function thingsEqual(thing1, thing2) {
    return thing1.place === thing2.place
        && thing1.name === thing2.name;
}

var things = [
  {place:"here",name:"stuff"},
  {place:"there",name:"morestuff"},
  {place:"there",name:"morestuff"}
];

removeDuplicates(things, thingsEqual);
console.log(things);

Jawaban ES3 asli

function arrayContains(arr, val, equals) {
    var i = arr.length;
    while (i--) {
        if ( equals(arr[i], val) ) {
            return true;
        }
    }
    return false;
}

function removeDuplicates(arr, equals) {
    var originalArr = arr.slice(0);
    var i, len, j, val;
    arr.length = 0;

    for (i = 0, len = originalArr.length; i < len; ++i) {
        val = originalArr[i];
        if (!arrayContains(arr, val, equals)) {
            arr.push(val);
        }
    }
}

function thingsEqual(thing1, thing2) {
    return thing1.place === thing2.place
        && thing1.name === thing2.name;
}

removeDuplicates(things.thing, thingsEqual);
Tim Down
sumber
1
Dua objek tidak akan mengevaluasi sama, bahkan jika mereka berbagi properti dan nilai yang sama.
kennebec
Ya saya tahu. Tapi pokoknya, saya gagal membaca pertanyaan dengan benar: Saya belum melihat bahwa itu adalah benda dengan sifat yang sama yang ia butuhkan untuk disingkirkan. Saya akan mengedit jawaban saya.
Tim Down
1
alih-alih saat berada di dalam arrayContains- gunakan metode Array.prototype..some Mengembalikan nilai true jika salah satu anggota array cocok dengan kondisi
MarkosyanArtur
13

Untuk menambahkan satu lagi ke daftar. Menggunakan ES6 dan Array.reducedengan Array.find.
Dalam contoh ini, memfilter objek berdasarkan guidproperti.

let filtered = array.reduce((accumulator, current) => {
  if (! accumulator.find(({guid}) => guid === current.guid)) {
    accumulator.push(current);
  }
  return accumulator;
}, []);

Memperluas yang ini untuk memungkinkan pemilihan properti dan kompres menjadi satu liner:

const uniqify = (array, key) => array.reduce((prev, curr) => prev.find(a => a[key] === curr[key]) ? prev : prev.push(curr) && prev, []);

Untuk menggunakannya, lewati array objek dan nama kunci yang ingin Anda hapus sebagai nilai string:

const result = uniqify(myArrayOfObjects, 'guid')
Pete B
sumber
11

Anda juga dapat menggunakan Map:

const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());

Sampel lengkap:

const things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});

const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());

console.log(JSON.stringify(dedupThings, null, 4));

Hasil:

[
    {
        "place": "here",
        "name": "stuff"
    },
    {
        "place": "there",
        "name": "morestuff"
    }
]
Pragmateek
sumber
+1, bagus untuk menjelaskan sedikit lebih dalam kerja dedupThings akan baik - di sisi baiknya sekarang saya mengerti mengurangi: D
MimiEAM
11

Sial, anak-anak, ayo hancurkan benda ini, kenapa kita tidak?

let uniqIds = {}, source = [{id:'a'},{id:'b'},{id:'c'},{id:'b'},{id:'a'},{id:'d'}];
let filtered = source.filter(obj => !uniqIds[obj.id] && (uniqIds[obj.id] = true));
console.log(filtered);
// EXPECTED: [{id:'a'},{id:'b'},{id:'c'},{id:'d'}];

Cliff Hall
sumber
Ini tidak menjawab pertanyaan awal karena ini mencari id. Pertanyaan ini membutuhkan seluruh objek menjadi unik di semua bidang seperti placedanname
L. Holanda
Ini adalah penyempurnaan dari generalisasi masalah di atas. Pertanyaan asli telah diposting 9 tahun yang lalu, jadi poster aslinya mungkin tidak mengkhawatirkan placedan namehari ini. Siapa pun yang membaca utas ini sedang mencari cara optimal untuk mendeduksi daftar objek, dan ini adalah cara ringkas untuk melakukannya.
Cliff Hall
11

Solusi TypeScript

Ini akan menghapus objek duplikat dan juga melestarikan jenis objek.

function removeDuplicateObjects(array: any[]) {
  return [...new Set(array.map(s => JSON.stringify(s)))]
    .map(s => JSON.parse(s));
}

sumber
2
ini bagus dan pendek!
mojjj
Dan super lambat juga ...
L. Holanda
7

Mengingat lodash.uniqWith

var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];

_.uniqWith(objects, _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
Justin
sumber
Sempurna! Terima kasih ;-)
DonFabiolas
1
Baik lodash tidak unik maupun unik. Tapi saya tidak berhasil, tetapi solusi Anda berhasil. Terima kasih! Tolong berikan sumber kode Anda, jika itu salinan langsung. lodash.com/docs/4.17.10#uniqDengan
Manu CJ
5

Pilihan lain adalah membuat fungsi indexOf kustom, yang membandingkan nilai properti yang Anda pilih untuk setiap objek dan membungkusnya dalam fungsi pengurangan.

var uniq = redundant_array.reduce(function(a,b){
      function indexOfProperty (a, b){
          for (var i=0;i<a.length;i++){
              if(a[i].property == b.property){
                   return i;
               }
          }
         return -1;
      }

      if (indexOfProperty(a,b) < 0 ) a.push(b);
        return a;
    },[]);
ZeroSum
sumber
ini berhasil bagi saya - saya memasangkan ini dengan lodash.isequalpaket npm sebagai pembanding objek ringan untuk melakukan penyaringan array yang unik ... misalnya array objek yang berbeda. Baru saja bertukar dan if (_.isEqual(a[i], b)) {bukannya mencari @ properti tunggal
SliverNinja - MSFT
5

let myData = [{place:"here",name:"stuff"}, 
 {place:"there",name:"morestuff"},
 {place:"there",name:"morestuff"}];


let q = [...new Map(myData.map(obj => [JSON.stringify(obj), obj])).values()];

console.log(q)

Satu-liner menggunakan ES6 dan new Map().

// assign things.thing to myData
let myData = things.thing;

[...new Map(myData.map(obj => [JSON.stringify(obj), obj])).values()];

Detail: -

  1. Melakukan .map()pada daftar data dan mengubah masing-masing objek menjadi [key, value]array pasangan (panjang = 2), elemen pertama (kunci) akan menjadi stringifiedversi objek dan yang kedua (nilai) akan menjadiobject dirinya sendiri.
  2. Menambahkan daftar array yang dibuat di atas new Map()akan memiliki kunci sebagaistringified objek dan penambahan kunci yang sama akan mengakibatkan menimpa kunci yang sudah ada.
  3. Menggunakan .values()akan memberi MapIterator dengan semua nilai dalam Peta (obj dalam kasus kami)
  4. Akhirnya, spread ...operator memberikan Array baru dengan nilai dari langkah di atas.
Savan Akbari
sumber
4

Ini adalah solusi untuk es6 di mana Anda hanya ingin menyimpan item terakhir. Solusi ini fungsional dan sesuai dengan gaya Airbnb.

const things = {
  thing: [
    { place: 'here', name: 'stuff' },
    { place: 'there', name: 'morestuff1' },
    { place: 'there', name: 'morestuff2' }, 
  ],
};

const removeDuplicates = (array, key) => {
  return array.reduce((arr, item) => {
    const removed = arr.filter(i => i[key] !== item[key]);
    return [...removed, item];
  }, []);
};

console.log(removeDuplicates(things.thing, 'place'));
// > [{ place: 'here', name: 'stuff' }, { place: 'there', name: 'morestuff2' }]
Mikha
sumber
Anda dapat menghapus duplikat dan Anda juga dapat menghapus semua duplikat dengan kode ini. Nice
sg28
4

removeDuplicates () mengambil dalam array objek dan mengembalikan array baru tanpa objek duplikat (berdasarkan properti id).

const allTests = [
  {name: 'Test1', id: '1'}, 
  {name: 'Test3', id: '3'},
  {name: 'Test2', id: '2'},
  {name: 'Test2', id: '2'},
  {name: 'Test3', id: '3'}
];

function removeDuplicates(array) {
  let uniq = {};
  return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true))
}

removeDuplicates(allTests);

Hasil yang diharapkan:

[
  {name: 'Test1', id: '1'}, 
  {name: 'Test3', id: '3'},
  {name: 'Test2', id: '2'}
];

Pertama, kita menetapkan nilai variabel uniq ke objek kosong.

Selanjutnya, kami memfilter melalui array objek. Filter membuat array baru dengan semua elemen yang lulus tes diimplementasikan oleh fungsi yang disediakan.

return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true));

Di atas, kami menggunakan fungsi hubungan singkat &&. Jika sisi kiri && dievaluasi ke true, maka ia mengembalikan nilai di sebelah kanan &&. Jika sisi kiri salah, ia mengembalikan apa yang ada di sisi kiri &&.

Untuk setiap objek (obj) kami memeriksa uniq untuk sebuah properti bernama nilai obj.id (Dalam hal ini, pada iterasi pertama ia akan memeriksa properti '1'.) Kami ingin kebalikan dari apa yang dikembalikan (baik benar atau salah) yang mengapa kami menggunakan! di! uniq [obj.id]. Jika uniq sudah memiliki properti id, ia mengembalikan true yang mengevaluasi false (!) Memberitahu fungsi filter TIDAK untuk menambahkan objek itu. Namun, jika tidak menemukan properti obj.id, ia mengembalikan false yang kemudian dievaluasi menjadi true (!) Dan mengembalikan semuanya ke kanan &&, atau (uniq [obj.id] = true). Ini adalah nilai kebenaran, memberi tahu metode filter untuk menambahkan objek ke array yang dikembalikan, dan juga menambahkan properti {1: true} ke uniq. Ini memastikan bahwa instance obj lain dengan id yang sama tidak akan ditambahkan lagi.

TandaiN
sumber
Mungkin menjelaskan kode Anda, dan bagaimana itu menjawab pertanyaan?
mix3d
Terima kasih, mix3d. Saya menambahkan klarifikasi.
MarkN
Terima kasih telah menjelaskan ini! Solusi ini bekerja untuk saya, dan mirip dengan beberapa orang lain yang diposting di sini, walaupun saya tidak mengerti apa yang sedang terjadi :)
Tim Molloy
3
let data = [
  {
    'name': 'Amir',
    'surname': 'Rahnama'
  }, 
  {
    'name': 'Amir',
    'surname': 'Stevens'
  }
];
let non_duplicated_data = _.uniqBy(data, 'name');
qzttt
sumber
9
Silakan tambahkan penjelasan di sekitar kode Anda sehingga pengunjung masa depan dapat memahami apa yang Anda lakukan. Terima kasih.
Bug
Jawaban Anda tergantung pada pustaka kode eksternal ...
Taylor A. Leach
3

Saya percaya kombinasi reducedengan JSON.stringifyuntuk membandingkan Objek secara sempurna dan secara selektif menambahkan mereka yang belum berada di akumulator adalah cara yang elegan.

Perlu diingat bahwa JSON.stringifymungkin menjadi masalah kinerja dalam kasus ekstrim di mana array memiliki banyak Objek dan mereka kompleks, TAPI untuk sebagian besar waktu , ini adalah cara terpendek untuk pergi IMHO.

var collection= [{a:1},{a:2},{a:1},{a:3}]

var filtered = collection.reduce((filtered, item) => {
  if( !filtered.some(filteredItem => JSON.stringify(filteredItem) == JSON.stringify(item)) )
    filtered.push(item)
  return filtered
}, [])

console.log(filtered)

Cara penulisan yang sama (tapi kurang efisien):

collection.reduce((filtered, item) => 
  filtered.some(filteredItem => 
    JSON.stringify(filteredItem ) == JSON.stringify(item)) 
      ? filtered
      : [...filtered, item]
, [])
vsync
sumber
salah satu yang bekerja untuk saya! Terima kasih!
javascript110899
2

Terus mengeksplorasi cara-cara ES6 untuk menghapus duplikat dari berbagai objek: menetapkan thisArgargumen Array.prototype.filteruntuk new Setmemberikan alternatif yang layak:

const things = [
  {place:"here",name:"stuff"},
  {place:"there",name:"morestuff"},
  {place:"there",name:"morestuff"}
];

const filtered = things.filter(function({place, name}) {

  const key =`${place}${name}`;

  return !this.has(key) && this.add(key);

}, new Set);

console.log(filtered);

Namun, itu tidak akan berfungsi dengan fungsi panah () =>, karena thisterikat dengan ruang lingkup leksikal mereka.

Leonid Pyrlia
sumber
2

es6 magic dalam satu baris ... dapat dibaca pada saat itu!

// returns the union of two arrays where duplicate objects with the same 'prop' are removed
const removeDuplicatesWith = (a, b, prop) => a.filter(x => !b.find(y => x[prop] === y[prop]);
Coosi Yosia
sumber
2

Solusi sederhana dengan metode bantu pengurangan ES6 'Perkecil' dan 'Temukan'

Bekerja dengan efisien dan sangat baik!

"use strict";

var things = new Object();
things.thing = new Array();
things.thing.push({
    place: "here",
    name: "stuff"
});
things.thing.push({
    place: "there",
    name: "morestuff"
});
things.thing.push({
    place: "there",
    name: "morestuff"
});

// the logic is here

function removeDup(something) {
    return something.thing.reduce(function (prev, ele) {
        var found = prev.find(function (fele) {
            return ele.place === fele.place && ele.name === fele.name;
        });
        if (!found) {
            prev.push(ele);
        }
        return prev;
    }, []);
}
console.log(removeDup(things));
KJ Sudarshan
sumber
Ini banyak membantu saya, terima kasih
jpisty
1

Jika Anda tidak keberatan array unik Anda diurutkan setelahnya, ini akan menjadi solusi yang efisien:

things.thing
  .sort(((a, b) => a.place < b.place)
  .filter((current, index, array) =>
    index === 0 || current.place !== array[index - 1].place)

Dengan cara ini, Anda hanya perlu membandingkan elemen saat ini dengan elemen sebelumnya dalam array. Mengurutkan sekali sebelum memfilter ( O(n*log(n))) lebih murah daripada mencari duplikat di seluruh array untuk setiap elemen array ( O(n²)).

Clemens Helm
sumber
1

Ini adalah cara sederhana cara menghapus duplikat dari berbagai objek.

Saya banyak bekerja dengan data dan ini berguna bagi saya.

const data = [{name: 'AAA'}, {name: 'AAA'}, {name: 'BBB'}, {name: 'AAA'}];
function removeDuplicity(datas){
    return datas.filter((item, index,arr)=>{
    const c = arr.map(item=> item.name);
    return  index === c.indexOf(item.name)
  })
}

console.log(removeDuplicity(data))

akan dicetak ke konsol:

[[object Object] {
name: "AAA"
}, [object Object] {
name: "BBB"
}]
Juraj
sumber
Solusi ini dirancang untuk menghapus duplikasi dari array statis, tetapi ketika Anda mendorong data dari backend ke dalam array data maka pertimbangkan untuk menggunakan ganti. Karena dalam kasus ini nilai baru yang didorong ke array data akan dihapus dan nilai "lama" akan tetap disimpan dalam array data.
Juraj
1
str =[
{"item_id":1},
{"item_id":2},
{"item_id":2}
]

obj =[]
for (x in str){
    if(check(str[x].item_id)){
        obj.push(str[x])
    }   
}
function check(id){
    flag=0
    for (y in obj){
        if(obj[y].item_id === id){
            flag =1
        }
    }
    if(flag ==0) return true
    else return false

}
console.log(obj)

str adalah array objek. Ada objek yang memiliki nilai yang sama (di sini contoh kecil, ada dua objek yang memiliki item_id sama dengan 2). check (id) adalah fungsi yang memeriksa apakah ada objek yang memiliki item_id yang sama ada atau tidak. jika ada return false jika tidak return true. Menurut hasil itu, mendorong objek ke array baru obj Output dari kode di atas adalah [{"item_id":1},{"item_id":2}]

Bibin Jaimon
sumber
Tambahkan deskripsi
Mathews Sunny
@Illa Apakah itu ok?
Bibin Jaimon
1

Pernahkah Anda mendengar tentang perpustakaan Lodash? Saya sarankan Anda utilitas ini, ketika Anda tidak benar-benar ingin menerapkan logika Anda ke kode, dan gunakan kode yang sudah ada yang dioptimalkan dan dapat diandalkan.

Pertimbangkan untuk membuat array seperti ini

things.thing.push({place:"utopia",name:"unicorn"});
things.thing.push({place:"jade_palace",name:"po"});
things.thing.push({place:"jade_palace",name:"tigress"});
things.thing.push({place:"utopia",name:"flying_reindeer"});
things.thing.push({place:"panda_village",name:"po"});

Perhatikan bahwa jika Anda ingin membuat satu atribut unik, Anda dapat melakukannya dengan menggunakan pustaka lodash. Di sini, Anda dapat menggunakan _.uniqBy

.uniqBy (array, [iteratee = .identity])

Metode ini seperti _.uniq (yang mengembalikan versi bebas duplikat dari array, di mana hanya kejadian pertama dari setiap elemen disimpan) kecuali bahwa ia menerima iteratee yang dipanggil untuk setiap elemen dalam array untuk menghasilkan kriteria yang dengannya Keunikan dihitung.

Jadi, misalnya, jika Anda ingin mengembalikan array yang memiliki atribut unik 'tempat'

_.uniqBy (things.thing, 'place')

Demikian pula, jika Anda ingin atribut unik sebagai 'nama'

_.uniqBy (things.thing, 'name')

Semoga ini membantu.

Bersulang!

Mayank Gangwal
sumber