Saya memiliki array objek JavaScript dengan struktur berikut:
objArray = [ { foo: 1, bar: 2}, { foo: 3, bar: 4}, { foo: 5, bar: 6} ];
Saya ingin mengekstrak bidang dari setiap objek, dan mendapatkan array yang berisi nilai-nilai, misalnya bidang foo
akan memberikan array [ 1, 3, 5 ]
.
Saya bisa melakukan ini dengan pendekatan sepele ini:
function getFields(input, field) {
var output = [];
for (var i=0; i < input.length ; ++i)
output.push(input[i][field]);
return output;
}
var result = getFields(objArray, "foo"); // returns [ 1, 3, 5 ]
Apakah ada cara yang lebih elegan atau idiomatis untuk melakukan ini, sehingga fungsi utilitas khusus tidak diperlukan?
Catatan tentang duplikat yang disarankan , ini mencakup cara mengkonversi objek tunggal ke array.
var foos = objArray.pluck("foo");
.Array.prototype.map
fungsi asli di mana ia adaJawaban:
Ini cara yang lebih singkat untuk mencapainya:
ATAU
Anda juga bisa memeriksanya
Array.prototype.map()
.sumber
Ya, tetapi ini bergantung pada fitur ES5 dari JavaScript. Ini berarti tidak akan berfungsi di IE8 atau lebih lama.
Pada penerjemah JS yang kompatibel dengan ES6, Anda dapat menggunakan fungsi panah untuk singkatnya:
Dokumentasi Array.prototype.map
sumber
foo
?var result = objArray.map((a) => (a.foo));
var result = objArray.map(a => a.foo);
Periksa fungsi Lodash
_.pluck()
atau fungsi Underscore_.pluck()
. Keduanya melakukan apa yang Anda inginkan dalam satu panggilan fungsi!Pembaruan:
_.pluck()
telah dihapus pada Lodash v4.0.0 , mendukung_.map()
dalam kombinasi dengan sesuatu yang mirip dengan jawaban Niet ._.pluck()
masih tersedia di Underscore .Pembaruan 2: Seperti yang ditunjukkan Mark dalam komentar , di suatu tempat antara Lodash v4 dan 4.3, fungsi baru telah ditambahkan yang menyediakan fungsionalitas ini lagi.
_.property()
adalah fungsi singkatan yang mengembalikan fungsi untuk mendapatkan nilai properti dalam objek.Selain itu,
_.map()
sekarang memungkinkan string untuk diteruskan sebagai parameter kedua, yang diteruskan ke_.property()
. Hasilnya, dua baris berikut ini setara dengan contoh kode di atas dari pra-Lodash 4._.property()
, dan karenanya_.map()
, juga memungkinkan Anda untuk memberikan string atau array yang dipisahkan titik untuk mengakses sub-properti:Kedua
_.map()
panggilan dalam contoh di atas akan kembali[5, 2, 9]
.Jika Anda sedikit lebih ke pemrograman fungsional, lihat fungsi Ramda
R.pluck()
, yang akan terlihat seperti ini:sumber
_.property('foo')
( lodash.com/docs#property ) ditambahkan sebagai singkatanfunction(o) { return o.foo; }
. Ini memperpendek kasus penggunaan Lodash kevar result = _.pluck(objArray, _.property('foo'));
Untuk kenyamanan lebih lanjut,_.map()
metode Lodash 4.3.0 juga memungkinkan penggunaan singkat di_.property()
bawah tenda, menghasilkanvar result = _.map(objArray, 'foo');
Berbicara untuk solusi JS saja, saya telah menemukan bahwa, mungkin keliru,
for
loop diindeks sederhana lebih berkinerja daripada alternatifnya.Mengekstrak properti tunggal dari array elemen 100000 (via jsPerf)
Tradisional untuk loop 368 Ops / dtk
ES6 untuk..dari loop 303 Ops / dtk
Array.prototype.map 19 Ops / dtk
TL; DR - .map () lambat, tetapi jangan ragu untuk menggunakannya jika Anda merasa keterbacaan bernilai lebih dari kinerja.
Edit # 2: 6/2019 - tautan jsPerf rusak, dihapus.
sumber
Lebih baik menggunakan beberapa jenis perpustakaan seperti lodash atau garis bawah untuk jaminan lintas browser.
Di Lodash Anda bisa mendapatkan nilai properti dalam array dengan metode berikut
dan di Garis Bawah
Keduanya akan kembali
sumber
Menggunakan
Array.prototype.map
:Lihat tautan di atas untuk shim untuk browser pra-ES5.
sumber
Di ES6, Anda dapat melakukan:
sumber
Meskipun
map
merupakan solusi yang tepat untuk memilih 'kolom' dari daftar objek, ia memiliki kelemahan. Jika tidak secara eksplisit memeriksa apakah ada kolom atau tidak, itu akan menimbulkan kesalahan dan (paling-paling) memberi Andaundefined
. Saya akan memilihreduce
solusi, yang dapat mengabaikan properti atau bahkan mengatur Anda dengan nilai default.contoh jsbin
Ini akan berfungsi bahkan jika salah satu item dalam daftar yang disediakan bukan objek atau tidak mengandung bidang.
Ia bahkan dapat dibuat lebih fleksibel dengan menegosiasikan nilai default jika suatu item tidak menjadi objek atau tidak mengandung bidang.
contoh jsbin
Ini akan sama dengan peta, karena panjang array yang dikembalikan akan sama dengan array yang disediakan. (Dalam hal ini a
map
sedikit lebih murah daripada areduce
):contoh jsbin
Dan kemudian ada solusi yang paling fleksibel, yang memungkinkan Anda beralih di antara kedua perilaku hanya dengan memberikan nilai alternatif.
contoh jsbin
Seperti contoh di atas (semoga) menjelaskan cara kerjanya, mari kita persingkat sedikit fungsinya dengan memanfaatkan
Array.concat
fungsinya.contoh jsbin
sumber
Secara umum, jika Anda ingin mengekstrapolasi nilai objek yang ada di dalam array (seperti dijelaskan dalam pertanyaan) maka Anda bisa menggunakan pengurangan, petakan peta dan array.
ES6
Penggunaan setara untuk dalam loop adalah:
Output yang dihasilkan: ["kata", "lagi", "beberapa", "1", "2", "3"]
sumber
Itu tergantung dari definisi Anda tentang "lebih baik".
Jawaban lain menunjukkan penggunaan peta, yang alami (terutama untuk pria yang terbiasa gaya fungsional) dan ringkas. Saya sangat merekomendasikan menggunakannya (jika Anda tidak repot-repot dengan beberapa IE8-IT guys). Jadi jika "lebih baik" berarti "lebih ringkas", "dapat dipelihara", "dapat dimengerti" maka ya, itu jauh lebih baik.
Di sisi lain, kecantikan ini tidak datang tanpa biaya tambahan. Saya bukan penggemar microbench, tapi saya sudah melakukan tes kecil di sini . Hasilnya bisa ditebak, cara jelek yang lama tampaknya lebih cepat daripada fungsi peta. Jadi jika "lebih baik" berarti "lebih cepat", maka tidak, tetaplah dengan mode sekolah lama.
Sekali lagi ini hanya microbench dan sama sekali tidak menganjurkan penggunaan
map
, itu hanya dua sen saya :).sumber
map
adalah cara untuk pergi, entah bagaimana saya gagal menemukannya dengan google (saya hanya menemukan peta jquery, yang tidak relevan).Jika Anda juga ingin mendukung objek mirip array, gunakan Array.from (ES2015):
Kelebihan yang dimilikinya dibandingkan metode Array.prototype.map () adalah inputnya juga bisa berupa Set :
sumber
Jika Anda ingin beberapa nilai dalam ES6 + yang berikut ini akan berfungsi
Ini berfungsi seperti
{foo, baz}
di sebelah kiri menggunakan penghancuran objek dan di sebelah kanan panah ekuivalen dengan{foo: foo, baz: baz}
karena literal objek ES6 yang ditingkatkan .sumber
Fungsi peta adalah pilihan yang baik ketika berhadapan dengan array objek. Meskipun sudah ada sejumlah jawaban bagus yang diposting, contoh penggunaan peta dengan kombinasi dengan filter mungkin bisa membantu.
Jika Anda ingin mengecualikan properti yang nilainya tidak ditentukan atau mengecualikan hanya properti tertentu, Anda bisa melakukan hal berikut:
https://jsfiddle.net/ohea7mgk/
sumber
Di atas jawaban yang diberikan baik untuk mengekstraksi properti tunggal, bagaimana jika Anda ingin mengekstraksi lebih dari satu properti dari berbagai objek. Ini solusinya !! Dalam hal itu kita cukup menggunakan _.pick (objek, [paths])
Mari kita asumsikan objArray memiliki objek dengan tiga properti seperti di bawah ini
Sekarang kita ingin mengekstrak properti foo dan bar dari setiap objek dan menyimpannya dalam array yang terpisah. Pertama kita akan mengulangi elemen array menggunakan peta dan kemudian kita menerapkan metode Lodash Library Standard _.pick () di atasnya.
Sekarang kita dapat mengekstrak properti 'foo' dan 'bar'.
var newArray = objArray.map((element)=>{ return _.pick(element, ['foo','bar'])}) console.log(newArray);
dan hasilnya adalah [{foo: 1, bar: 2}, {foo: 3, bar: 4}, {foo: 5, bar: 6}]
Nikmati!!!
sumber
_.pick
? Ini bukan fungsi standar.Jika Anda memiliki array bersarang, Anda dapat membuatnya berfungsi seperti ini:
sumber