Pertanyaan Dapatkan semua nilai unik dalam susunan JavaScript (hapus duplikat)


Saya memiliki sejumlah angka yang harus saya pastikan unik. Saya menemukan potongan kode di bawah ini di internet dan bekerja dengan baik sampai array memiliki nol di dalamnya. saya menemukan naskah lain ini di sini di SO yang terlihat hampir persis seperti itu, tetapi itu tidak gagal.

Jadi, demi membantu saya belajar, dapatkah seseorang membantu saya menentukan di mana skrip prototipe itu salah?

Array.prototype.getUnique = function() {
 var o = {}, a = [], i, e;
 for (i = 0; e = this[i]; i++) {o[e] = 1};
 for (e in o) {a.push (e)};
 return a;
}

Lebih banyak jawaban dari pertanyaan duplikat:

Pertanyaan serupa:


779
2017-12-25 04:28


asal


Jawaban:


Dengan JavaScript 1.6 / ECMAScript 5 Anda dapat menggunakan asli filter metode Array dengan cara berikut untuk mendapatkan larik dengan nilai unik:

function onlyUnique(value, index, self) { 
    return self.indexOf(value) === index;
}

// usage example:
var a = ['a', 1, 'a', 2, '1'];
var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']

Metode asli filter akan mengulang melalui array dan hanya meninggalkan entri yang melewati fungsi callback yang diberikan onlyUnique.

onlyUnique cek, jika nilai yang diberikan adalah yang pertama terjadi. Jika tidak, itu harus duplikat dan tidak akan disalin.

Solusi ini berfungsi tanpa pustaka tambahan seperti jQuery atau prototype.js.

Ia berfungsi untuk array dengan tipe nilai campuran juga.

Untuk Browser lama (<IE9), yang tidak mendukung metode asli filter dan indexOf Anda dapat menemukan work around dalam dokumentasi MDN untuk menyaring dan Indeks.

Jika Anda ingin menyimpan kejadian terakhir dari sebuah nilai, gantilah dengan mudah indexOf oleh lastIndexOf.

Dengan ES6, ini bisa dipersingkat menjadi ini:

// usage example:
var myArray = ['a', 1, 'a', 2, '1'];
var unique = myArray.filter((v, i, a) => a.indexOf(v) === i); 

// unique is ['a', 1, 2, '1']

Terimakasih untuk Camilo Martin untuk petunjuk dalam komentar.

ES6 memiliki objek asli Set untuk menyimpan nilai-nilai unik. Untuk mendapatkan larik dengan nilai unik, Anda dapat melakukannya sekarang:

var myArray = ['a', 1, 'a', 2, '1'];

let unique = [...new Set(myArray)]; 

// unique is ['a', 1, 2, '1']

Konstruktor dari Set mengambil objek iterable, seperti Array, dan operator spread ... mengubah set kembali ke Array. Terimakasih untuk Lukas Liese untuk petunjuk dalam komentar.


1465
2018-01-21 12:46



Jawaban diperbarui untuk ES6 / ES2015: Menggunakan Set, solusi satu baris adalah:

var items = [4,5,4,6,3,4,5,2,23,1,4,4,4]
var uniqueItems = Array.from(new Set(items))

Yang mengembalikan

[4, 5, 6, 3, 2, 23, 1]

Sebagai le_m disarankan, ini juga dapat disingkat menggunakan operator menyebar , suka

var uniqueItems = [...new Set(items)]

488
2017-10-14 09:42



Anda juga bisa menggunakan underscore.js.

console.log(_.uniq([1, 2, 1, 3, 1, 4]));
<script src="http://underscorejs.org/underscore-min.js"></script>

yang akan mengembalikan:

[1, 2, 3, 4]

116
2017-07-11 16:25



Saya menyadari pertanyaan ini sudah lebih dari 30 jawaban. Tetapi saya telah membaca semua jawaban yang ada terlebih dahulu dan membuat penelitian saya sendiri.

Saya membagi semua jawaban atas 4 solusi yang memungkinkan:

  1. Gunakan fitur ES6 baru: [...new Set( [1, 1, 2] )];
  2. Gunakan objek { } untuk mencegah duplikat
  3. Gunakan helper array [ ]
  4. Menggunakan filter + indexOf

Berikut ini kode sampel yang ditemukan dalam jawaban:

Gunakan fitur ES6 baru: [...new Set( [1, 1, 2] )];

function uniqueArray0(array) {
  var result = Array.from(new Set(array));
  return result    
}

Gunakan objek { } untuk mencegah duplikat

function uniqueArray1( ar ) {
  var j = {};

  ar.forEach( function(v) {
    j[v+ '::' + typeof v] = v;
  });

  return Object.keys(j).map(function(v){
    return j[v];
  });
} 

Gunakan helper array [ ]

function uniqueArray2(arr) {
    var a = [];
    for (var i=0, l=arr.length; i<l; i++)
        if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
            a.push(arr[i]);
    return a;
}

Menggunakan filter + indexOf

function uniqueArray3(a) {
  function onlyUnique(value, index, self) { 
      return self.indexOf(value) === index;
  }

  // usage
  var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']

  return unique;
}

Dan saya bertanya-tanya mana yang lebih cepat. Saya sudah membuat contoh Google Spreadsheet untuk menguji fungsi. Catatan: ECMA 6 tidak tersedia di Google Spreadsheet, jadi saya tidak bisa mengujinya.

Inilah hasil dari tes: enter image description here

Saya berharap untuk melihat kode itu menggunakan objek { } akan menang karena menggunakan hash. Jadi saya senang bahwa tes menunjukkan hasil terbaik untuk algoritme ini di Chrome dan IE. Terima kasih kepada @rab untuk Kode.


87
2018-03-27 12:24



Sejak itu saya menemukan metode bagus yang menggunakan jQuery

arr = $.grep(arr, function(v, k){
    return $.inArray(v ,arr) === k;
});

Catatan: Kode ini ditarik dari Bebek Paul Irlandia meninju - Saya lupa memberikan kredit: P


51
2017-07-12 15:41



Satu Liner, JavaScript Murni

Dengan sintaks ES6

list = list.filter((x, i, a) => a.indexOf(x) == i)

x --> item in array
i --> index of item
a --> array reference, (in this case "list")

enter image description here

Dengan sintaks ES5

list = list.filter(function (x, i, a) { 
    return a.indexOf(x) == i; 
});

Kompatibilitas Browser: IE9 +


44
2017-09-01 13:32



Solusi terpendek dengan ES6: [...new Set( [1, 1, 2] )];

Atau jika Anda ingin memodifikasi prototipe Array (seperti dalam pertanyaan asli):

Array.prototype.getUnique = function() {
    return [...new Set( [this] )];
};

EcmaScript 6 hanya sebagian diimplementasikan di browser modern saat ini (Agustus 2015), namun Babel telah menjadi sangat populer untuk transpining ES6 (dan bahkan ES7) kembali ke ES5. Dengan begitu Anda dapat menulis kode ES6 hari ini!

Jika Anda bertanya-tanya apa itu ... berarti, itu disebut operator menyebar. Dari MDN: "Operator penyebaran memungkinkan ekspresi diperluas di tempat-tempat di mana banyak argumen (untuk panggilan fungsi) atau beberapa elemen (untuk literal array) diharapkan". Karena Set adalah iterable (dan hanya dapat memiliki nilai unik), operator spread akan memperluas Set untuk mengisi array.

Sumber daya untuk mempelajari ES6:


39
2018-04-23 12:42



Solusi paling sederhana:

var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
console.log([...new Set(arr)]);

Atau:

var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
console.log(Array.from(new Set(arr)));


31
2018-03-14 22:01



Yang paling sederhana, dan tercepat (dalam Chrome) cara melakukan ini:

Array.prototype.unique = function() {
    var a = [];
    for (var i=0, l=this.length; i<l; i++)
        if (a.indexOf(this[i]) === -1)
            a.push(this[i]);
    return a;
}

Cukup melalui setiap item dalam array, tes jika item tersebut sudah ada dalam daftar, dan jika tidak, tekan ke array yang akan dikembalikan.

Menurut jsPerf, fungsi ini yang tercepat dari yang bisa saya temukan di mana saja - Jangan ragu untuk menambahkan milikmu sendiri.

Versi non-prototipe:

function uniques(arr) {
    var a = [];
    for (var i=0, l=arr.length; i<l; i++)
        if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
            a.push(arr[i]);
    return a;
}

Penyortiran

Ketika juga perlu mengurutkan array, berikut ini adalah yang tercepat:

Array.prototype.sortUnique = function() {
    this.sort();
    var last_i;
    for (var i=0;i<this.length;i++)
        if ((last_i = this.lastIndexOf(this[i])) !== i)
            this.splice(i+1, last_i-i);
    return this;
}

atau non-prototipe:

function sortUnique(arr) {
    arr.sort();
    var last_i;
    for (var i=0;i<arr.length;i++)
        if ((last_i = arr.lastIndexOf(arr[i])) !== i)
            arr.splice(i+1, last_i-i);
    return arr;
}

Ini juga lebih cepat dari metode di atas di sebagian besar browser non-chrome.


30
2018-01-30 00:10