Dengan asumsi saya memiliki yang berikut ini:
var array =
[
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35}
]
Apa cara terbaik untuk bisa mendapatkan array dari semua umur yang berbeda sehingga saya mendapatkan array hasil:
[17, 35]
Apakah ada beberapa cara saya bisa menyusun data atau metode yang lebih baik sehingga saya tidak perlu beralih melalui setiap array memeriksa nilai "usia" dan memeriksa terhadap array lain untuk keberadaannya, dan menambahkannya jika tidak?
Jika ada cara saya bisa menarik usia yang berbeda tanpa iterasi ...
Cara tidak efisien saat ini saya ingin meningkatkan ... Jika itu berarti bahwa alih-alih "array" menjadi array objek, tetapi "peta" objek dengan beberapa kunci unik (yaitu "1,2,3") yang akan menjadi oke juga. Saya hanya mencari cara yang paling efisien kinerja.
Berikut ini adalah bagaimana saya saat ini melakukannya, tetapi bagi saya, iterasi tampaknya hanya payah untuk efisiensi meskipun itu berfungsi ...
var distinct = []
for (var i = 0; i < array.length; i++)
if (array[i].age not in distinct)
distinct.push(array[i].age)
sumber
Set
objek danmap
s boros. Pekerjaan ini hanya membutuhkan.reduce()
tahap sederhana .Jawaban:
Jika ini PHP, saya akan membuat array dengan kunci dan mengambil
array_keys
pada akhirnya, tetapi JS tidak memiliki kemewahan seperti itu. Alih-alih, coba ini:sumber
array_unique
akan membandingkan seluruh item, bukan hanya usia seperti yang diminta di sini.flags = {}
lebih baik daripadaflags = []
age
adalah integer yang relatif kecil (<120 pasti)Jika Anda menggunakan ES6 / ES2015 atau lebih baru, Anda dapat melakukannya dengan cara ini:
Berikut adalah contoh cara melakukannya.
sumber
TypeError: (intermediate value).slice is not a function
menggunakan ES6
sumber
array.filter((value, index, self) => self.map(x => x.age).indexOf(value.age) == index)
Anda bisa menggunakan pendekatan kamus seperti ini. Pada dasarnya Anda menetapkan nilai yang ingin Anda bedakan sebagai kunci dalam "kamus" (di sini kami menggunakan array sebagai objek untuk menghindari mode kamus). Jika kunci tidak ada maka Anda menambahkan nilai itu sebagai berbeda.
Ini demo yang berfungsi:
Ini akan menjadi O (n) di mana n adalah jumlah objek dalam array dan m adalah jumlah nilai unik. Tidak ada cara yang lebih cepat daripada O (n) karena Anda harus memeriksa setiap nilai setidaknya satu kali.
Versi sebelumnya ini menggunakan objek, dan untuk in. Ini sifatnya minor, dan sejak itu sedikit diperbarui di atas. Namun, alasan tampaknya kemajuan dalam kinerja antara dua versi di jsperf asli adalah karena ukuran sampel data yang sangat kecil. Dengan demikian, perbandingan utama dalam versi sebelumnya adalah melihat perbedaan antara peta internal dan penggunaan filter versus pencarian mode kamus.
Saya telah memperbarui kode di atas, sebagaimana dicatat, namun, saya juga memperbarui jsperf untuk melihat melalui 1000 objek, bukan 3. 3 mengabaikan banyak jebakan kinerja yang terlibat ( jsperf usang ).
Performa
https://jsperf.com/filter-vs-dictionary-more-data Ketika saya menjalankan kamus ini 96% lebih cepat.
sumber
if( typeof(unique[array[i].age]) == "undefined"){ distinct.push(array[i].age); unique[array[i].age] = 0; }
Ini adalah bagaimana Anda akan menyelesaikan ini menggunakan Set baru melalui ES6 untuk mengeskrip pada 25 Agustus 2017
sumber
Menggunakan fitur ES6, Anda dapat melakukan sesuatu seperti:
sumber
const uniqueObjects = [ ...new Set( array.map( obj => obj.age) ) ].map( age=> { return array.find(obj => obj.age === age) } )
Saya baru saja memetakan dan menghapus dups:
Sunting: Aight! Bukan cara yang paling efisien dalam hal kinerja, tetapi IMO yang paling mudah dibaca. Jika Anda benar-benar peduli tentang optimasi mikro atau Anda memiliki jumlah data yang besar, maka
for
perulangan reguler akan lebih "efisien".sumber
if
s. Anda akan mendapatkan hasil yang sangat berbeda dengan tiga juta.Contoh ES6
sumber
Bagi mereka yang ingin mengembalikan objek dengan semua properti unik dengan kunci
sumber
Sudah banyak jawaban yang valid, tetapi saya ingin menambahkan satu yang hanya menggunakan
reduce()
metode karena bersih dan sederhana.Gunakan seperti ini:
sumber
The
forEach
Versi jawaban @ travis-j ini (membantu pada browser modern dan dunia Node JS):34% lebih cepat di Chrome v29.0.1547: http://jsperf.com/filter-versus-dictionary/3
Dan solusi umum yang mengambil fungsi mapper (sedikit lebih lambat dari peta langsung, tapi itu diharapkan):
sumber
Saya sudah mulai menempel Garis Bawah di semua proyek baru secara default, jadi saya tidak pernah harus memikirkan masalah kecil data-munging ini.
Menghasilkan
[17, 35]
.sumber
Berikut cara lain untuk menyelesaikan ini:
Saya tidak tahu seberapa cepat solusi ini dibandingkan dengan yang lain, tapi saya suka tampilan yang lebih bersih. ;-)
EDIT: Oke, di atas tampaknya menjadi solusi paling lambat di sini.
Saya telah membuat case test kinerja di sini: http://jsperf.com/distinct-values-from-array
Alih-alih menguji untuk usia (Integer), saya memilih untuk membandingkan nama (Strings).
Metode 1 (solusi TS) sangat cepat. Yang cukup menarik, Metode 7 mengungguli semua solusi lain, di sini saya baru saja menyingkirkan .indexOf () dan menggunakan implementasi "manual", menghindari panggilan fungsi yang berulang:
Perbedaan dalam kinerja menggunakan Safari & Firefox adalah luar biasa, dan sepertinya Chrome melakukan pekerjaan terbaik pada optimasi.
Saya tidak begitu yakin mengapa cuplikan di atas sangat cepat dibandingkan dengan yang lain, mungkin seseorang yang lebih bijak dari saya punya jawabannya. ;-)
sumber
menggunakan lodash
sumber
Menggunakan Lodash
Pengembalian [17,35]
sumber
sumber
underscore.js
_.uniq(_.pluck(array,"age"))
sumber
Berikut adalah solusi serbaguna yang menggunakan pengurangan, memungkinkan untuk pemetaan, dan mempertahankan urutan penyisipan.
barang : sebuah array
mapper : Fungsi unary yang memetakan item ke kriteria, atau kosong untuk memetakan item itu sendiri.
Pemakaian
Anda dapat menambahkan ini ke prototipe Array Anda dan meninggalkan parameter item jika itu gaya Anda ...
Anda juga dapat menggunakan Set alih-alih Array untuk mempercepat pencocokan.
sumber
sumber
Baru saja menemukan ini dan saya pikir ini berguna
Sekali lagi menggunakan garis bawah , jadi jika Anda memiliki objek seperti ini
itu akan memberi Anda objek unik saja.
Apa yang terjadi di sini adalah
indexBy
mengembalikan peta seperti inidan hanya karena ini peta, semua kunci unik.
Lalu saya hanya memetakan daftar ini kembali ke array.
Jika Anda hanya perlu nilai yang berbeda
Perlu diingat bahwa
key
dikembalikan sebagai string sehingga, jika Anda membutuhkan bilangan bulat, Anda harus melakukannyasumber
saya pikir Anda mencari fungsi groupBy (menggunakan Lodash)
menghasilkan hasil:
Demo jsFiddle: http://jsfiddle.net/4J2SX/201/
sumber
Jika seperti saya Anda lebih suka yang lebih "fungsional" tanpa mengurangi kecepatan, contoh ini menggunakan kamus cepat yang dibungkus di dalam mengurangi penutupan.
Menurut tes ini solusi saya dua kali lebih cepat dari jawaban yang diusulkan
sumber
sumber
Saya tahu kode saya sedikit panjang dan sedikit kompleksitas waktu tetapi dapat dimengerti jadi saya mencoba cara ini.
Saya mencoba mengembangkan fungsi berbasis prototipe di sini dan kode juga berubah.
Di sini, Distinct adalah fungsi prototipe saya sendiri.
sumber
Jika Anda memiliki Array.prototype.includes atau bersedia untuk mengisinya , ini berfungsi:
sumber
Kode saya di bawah ini akan menunjukkan array umur yang unik dan juga array baru yang tidak memiliki usia duplikat
sumber
Saya menulis sendiri di TypeScript, untuk kasus generik, seperti itu di Kotlin
Array.distinctBy {}
...Di mana
U
hashable, tentu saja. Untuk Objek, Anda mungkin perlu https://www.npmjs.com/package/es6-json-stable-stringifysumber
Jika Anda perlu objek unik yang unik
[Obyek {x: 1, y: 2}, Obyek {x: 2, y: 1}]
sumber
Menjawab pertanyaan lama ini tidak ada gunanya, tetapi ada jawaban sederhana yang berbicara tentang sifat Javascript. Objek dalam Javascript pada dasarnya adalah tabel hash. Kita dapat menggunakan ini untuk mendapatkan hash kunci unik:
Lalu kita bisa mengurangi hash ke array nilai unik:
Itu yang kamu butuhkan. Array a2 hanya berisi usia unik.
sumber
Satu garis sederhana dengan kinerja luar biasa. 6% lebih cepat dari solusi ES6 dalam pengujian saya .
sumber
array.map( o => o.age).filter( (v,i,a) => a.indexOf(v)===i)
. Saya menggunakan fungsi kunci sangat jarang sekarang bahwa saya harus membaca hal-hal dua kali ketika saya melihatnya 😊