Saya punya objek:
myObject = { 'a': 1, 'b': 2, 'c': 3 }
Saya mencari metode asli, mirip dengan Array.prototype.map
yang akan digunakan sebagai berikut:
newObject = myObject.map(function (value, label) {
return value * value;
});
// newObject is now { 'a': 1, 'b': 4, 'c': 9 }
Apakah JavaScript memiliki map
fungsi untuk objek seperti itu? (Saya ingin ini untuk Node.JS, jadi saya tidak peduli tentang masalah lintas-browser.)
javascript
node.js
functional-programming
map-function
Randomblue
sumber
sumber
Object.keys
, yang tidak memiliki urutan yang jelas. Itu bisa bermasalah, saya sarankan menggunakanObject.getOwnPropertyNames
sebagai gantinya.Object.keys
danObject.getOwnPropertyNames
. Lihat developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Object.keys
tergantung pada implementasi. Lihat stackoverflow.com/a/30919039/1529630Jawaban:
Tidak ada yang asli
map
padaObject
objek, tetapi bagaimana dengan ini:Tapi Anda bisa dengan mudah beralih pada objek menggunakan
for ... in
:Memperbarui
Banyak orang menyebutkan bahwa metode sebelumnya tidak mengembalikan objek baru, tetapi beroperasi pada objek itu sendiri. Untuk itu saya ingin menambahkan solusi lain yang mengembalikan objek baru dan meninggalkan objek aslinya seperti:
Array.prototype.reduce
mengurangi array ke nilai tunggal dengan cara menggabungkan nilai sebelumnya dengan arus. Rantai diinisialisasi oleh objek kosong{}
. Pada setiap iterasi kunci barumyObject
ditambahkan dengan dua kali kunci sebagai nilainya.Memperbarui
Dengan fitur ES6 baru, ada cara yang lebih elegan untuk berekspresi
objectMap
.sumber
map
dengan benar karena tidak melakukanreturn
- itu menyalahgunakanmap
seolah-olah ituforEach
panggilan. Jika dia benar - benar melakukannyareturn myObject[value] * 2
maka hasilnya akan menjadi array yang berisi nilai-nilai asli dua kali lipat, bukan objek yang berisi kunci asli dengan nilai-nilai dua kali lipat, yang terakhir jelas menjadi apa yang diminta OP..reduce
contoh Anda OK, tapi IMHO masih jauh dari kenyamanan.map
untuk Objek, karena.reduce
panggilan balik Anda tidak hanya harus cocok dengan cara yang.reduce
bekerja, tetapi juga mengharuskan itumyObject
tersedia dalam lingkup leksikal. Yang terakhir khususnya membuatnya tidak mungkin untuk hanya melewati referensi fungsi di callback, membutuhkan fungsi anonim di tempat sebagai gantinya.Bagaimana dengan satu liner dengan penugasan variabel langsung di JS polos ( ES6 / ES2015 )?
Memanfaatkan operator spread dan sintaks nama kunci yang dikomputasi :
jsbin
Versi lain menggunakan pengurangan:
jsbin
Contoh pertama sebagai fungsi:
jsbin
Jika Anda ingin memetakan objek bersarang secara rekursif dalam gaya fungsional , itu bisa dilakukan seperti ini:
jsbin
Atau lebih penting lagi, seperti ini:
jsbin
Karena ES7 / ES2016 Anda dapat menggunakan,
Object.entries()
bukanObject.keys()
misalnya, seperti ini:ES2019 diperkenalkan
Object.fromEntries()
, yang semakin menyederhanakan ini:Properti yang diwariskan dan rantai prototipe:
Dalam beberapa situasi yang jarang terjadi, Anda mungkin perlu memetakan objek seperti kelas yang menyimpan properti dari objek yang diwarisi pada rantai prototipe-nya . Dalam kasus seperti itu
Object.keys()
tidak akan berfungsi, karenaObject.keys()
tidak menyebutkan properti yang diwarisi . Jika Anda perlu memetakan properti yang diwarisi , Anda harus menggunakanfor (key in myObj) {...}
.Berikut adalah contoh dari objek yang mewarisi properti dari objek lain dan bagaimana
Object.keys()
tidak bekerja dalam skenario seperti itu.jsbin
Namun, tolong bantu saya dan hindari warisan . :-)
sumber
Object.keys
tidak menyebutkan properti warisan. Saya sarankan Anda menambahkan peringatan.Object.entries({a: 1, b: 2, c: 3})
.(o, f)
sebagai argumen tetapi digunakanobj
dalam tubuh.Object.assign(...Object.entries(obj).map(([k, v]) => ({[k]: v * v})))
tidak berfungsi jikaobj
benda kosong. Ubah ke:Object.assign({}, ...Object.entries(obj).map(([k, v]) => ({[k]: v * v})))
.Tidak ada metode asli, tetapi lodash # mapValues akan melakukan pekerjaan dengan cemerlang
sumber
Object.entries({a: 1, b: 2, c: 3})
untuk mendapatkan array._.map()
sehingga Anda mendapatkan kunci sebagai argumen kedua - seperti yang disyaratkan oleh OP._.mapValues()
tidak juga menyediakan kunci sebagai argumen ke-2. Juga_.map()
tidak akan bekerja di sini karena hanya mengembalikan array, bukan objek:_.map({ 'a': 1, 'b': 2, 'c': 3}, n => n * 3) // [3, 6, 9]
Cukup mudah untuk menulis satu:
dengan kode contoh:
NB: versi ini juga memungkinkan Anda untuk (secara opsional) mengatur
this
konteks panggilan balik, sama sepertiArray
metode.EDIT - diubah untuk menghapus penggunaan
Object.prototype
, untuk memastikan tidak berbenturan dengan properti yang ada yang disebutkanmap
pada objek.sumber
map
, tetapi saya harus mengatakan bahwa memodifikasiObject.prototype
tidak cocok dengan saya, bahkan jika itu tidak dapat dihitung.Object.prototype
selain (secara teoritis) risiko tabrakan dengan metode lain. FWIW, saya tidak bisa mengerti bagaimana jawaban yang lain mendapat suara sebanyak itu, itu benar-benar salah.o = {map: true, image: false}
. Anda mempertaruhkannya hanya dengan menuliso.map(fn)
alih-alihmap(o,fn)
Anda bisa menggunakan
Object.keys
dan kemudianforEach
melewati susunan kunci yang dikembalikan:Atau dengan cara yang lebih modular:
Perhatikan bahwa
Object.keys
mengembalikan array yang hanya berisi properti enumerable objek sendiri, sehingga berperilaku sepertifor..in
loop dengan tandahasOwnProperty
centang.sumber
Ini lurus bs, dan semua orang di komunitas JS tahu itu. Ada harus menjadi fungsi ini:
di sini adalah implementasi naif:
itu sangat menjengkelkan harus mengimplementasikan ini sendiri setiap saat;)
Jika Anda menginginkan sesuatu yang sedikit lebih canggih, yang tidak mengganggu kelas Object, coba ini:
tetapi aman untuk menambahkan fungsi peta ini ke Object, tapi jangan menambahkan Object.prototype.
sumber
Object
objek global ? Hanya punyaconst mapObject = (obj, fn) => { [...]; return ret; }
..map
secara umum dipahami sebagai antarmuka Functor, dan tidak ada definisi tunggal Functor untuk "Objek" karena hampir semua hal dalam javascript dapat menjadi Obyek, termasuk hal-hal dengan antarmuka / logika .map / logika.Saya datang ke sini mencari untuk menemukan dan menjawab untuk memetakan objek ke array dan mendapatkan halaman ini sebagai hasilnya. Jika Anda datang ke sini mencari jawaban yang sama dengan saya, berikut adalah cara Anda dapat memetakan dan menolak array.
Anda dapat menggunakan peta untuk mengembalikan array baru dari objek seperti:
sumber
Object.values(myObject)
Jawaban yang diterima memiliki dua kelemahan:
Array.prototype.reduce
, karena mengurangi berarti mengubah struktur tipe komposit, yang tidak terjadi dalam kasus ini.Pendekatan fungsional ES6 / ES2015
Harap dicatat bahwa semua fungsi didefinisikan dalam bentuk kari.
o
ditugaskan kembali. Karena Javascript melewati nilai referensi dengan berbagi , salinan dangkalo
dihasilkan. Kita sekarang dapat bermutasi dio
dalamomap
tanpa bermutasio
dalam lingkup induk.map
nilai pengembalian diabaikan, karenamap
melakukan mutasio
. Karena efek samping ini tetap ada di dalamomap
dan tidak terlihat dalam lingkup induk, itu sepenuhnya dapat diterima.Ini bukan solusi tercepat, tetapi yang deklaratif dan dapat digunakan kembali. Berikut ini adalah implementasi yang sama dengan satu baris, ringkas tapi kurang mudah dibaca:
Tambahan - mengapa objek tidak dapat diubah secara default?
ES2015 menetapkan protokol iterator dan iterable. Tetapi benda-benda masih tidak bisa diubah dan karenanya tidak bisa dipetakan. Alasannya adalah pencampuran data dan tingkat program .
sumber
Array.prototype.reduce
keduanya. Yang ingin saya ilustrasikan di sini adalah bahwa jawaban yang diterima entah bagaimana "menyalahgunakan"Array.prototype.reduce
dan bagaimana pemetaan yang murni fungsional dapat diimplementasikan. Jika Anda tidak tertarik pada pemrograman fungsional, abaikan saja jawaban saya.fold
lebih umum daripadamap
(functor). Namun, ini adalah pengetahuan saya dari pertengahan 2016. Itu setengah keabadian: DJavaScript baru saja mendapatkan
Object.fromEntries
metode baru .Contoh
Penjelasan
Kode di atas mengubah Objek menjadi Array bersarang (
[[<key>,<value>], ...]
) yang dapat Anda petakan.Object.fromEntries
mengubah Array kembali ke Object.Yang keren tentang pola ini, adalah bahwa Anda sekarang dapat dengan mudah mengambil kunci objek ke akun saat memetakan.
Dokumentasi
Object.fromEntries()
Object.entries()
Dukungan Browser
Object.fromEntries
saat ini hanya didukung oleh peramban / mesin ini , namun ada polyfill yang tersedia (mis. @ babel / polyfill ).sumber
Object.fromEntries
kebalikan dariObject.entries
.Object.entries
mengonversi objek ke daftar pasangan nilai kunci.Object.fromEntries
mengonversi daftar pasangan nilai kunci ke objek.Versi minimal (es6):
sumber
Object.entries(obj).reduce((a, [k, v]) => [a[k] = v * v, a], {})
, kurung-siku bukan tanda kurung.Object.entries(obj).reduce((a, [k, v]) => {a[k] = v * v; return a}, {})
Object.entries().reduce
adalah solusi terbaik yang saya pikir dengan ES6 +. Akan mendapatkan lebih banyak upvotes jika menggunakanreturn
pernyataan dalam peredam daripadaimplicit return
dancomma
operator - yang rapi tapi sulit dibaca IMHOUntuk kinerja maksimal.
Jika objek Anda tidak sering berubah tetapi perlu diulangi sering saya sarankan menggunakan Peta asli sebagai cache.
Object.entries sudah berfungsi di Chrome, Edge, Firefox dan beta Opera jadi ini fitur yang tahan masa depan. Ini dari ES7 jadi polyfill https://github.com/es-shims/Object.entries untuk IE yang tidak berfungsi.
sumber
const fn = v => v * 2; const newObj = Object.entries(myObject).reduce((acc, [k,v]) => Object.assign({}, acc, {[k]: fn(v)}), {});
Anda dapat menggunakan
map
metode danforEach
pada array tetapi jika Anda ingin menggunakannyaObject
maka Anda dapat menggunakannya dengan twist seperti di bawah ini:Menggunakan Javascript (ES6)
Menggunakan jQuery
Atau Anda dapat menggunakan loop lain juga seperti
$.each
metode seperti contoh di bawah ini:sumber
$
jquery?Tidak
map function
ada padaObject.prototype
namun Anda dapat meniru seperti itusumber
typeof callback === 'function'
benar-benar berlebihan. 1)map
tidak memiliki arti tanpa panggilan balik 2) jikacallback
tidak berfungsi,map
implementasi Anda hanya berjalan tanpa makna untuk-loop. Juga,Object.prototype.hasOwnProperty.call( obj, key )
sedikit berlebihan.Saya menemukan ini sebagai item pertama dalam pencarian Google yang mencoba belajar untuk melakukan ini, dan saya pikir saya akan berbagi untuk folsk lain menemukan ini baru-baru ini solusi yang saya temukan, yang menggunakan paket npm tidak dapat diubah.
Saya pikir ini menarik untuk dibagikan karena immutable menggunakan situasi OP EXACT dalam dokumentasi mereka sendiri - berikut ini bukan kode saya sendiri tetapi ditarik dari dokumentasi immutable-js saat ini:
Bukan berarti Seq memiliki properti lain ("Seq menggambarkan operasi malas, memungkinkan mereka untuk secara efisien menggunakan semua metode pengumpulan tingkat tinggi (seperti peta dan filter) dengan tidak membuat koleksi perantara") dan bahwa beberapa data js lainnya yang tidak dapat diubah struktur mungkin juga melakukan pekerjaan dengan cukup efisien.
Siapa pun yang menggunakan metode ini tentu saja harus
npm install immutable
dan mungkin ingin membaca dokumen:https://facebook.github.io/immutable-js/
sumber
EDIT: Cara kanonik menggunakan fitur JavaScript yang lebih baru adalah -
Di mana
o
beberapa objek danf
fungsi pemetaan Anda. Atau kita dapat mengatakan, diberi fungsi daria -> b
, dan objek dengan nilai tipea
, menghasilkan objek dengan nilai tipeb
. Sebagai tanda tangan tipe semu -Jawaban aslinya ditulis untuk menunjukkan kombinasi yang kuat,
mapReduce
yang memungkinkan kita untuk memikirkan transformasi kita dengan cara yang berbedam
, fungsi pemetaan - memberi Anda kesempatan untuk mengubah elemen yang masuk sebelum ...r
, fungsi pereduksi - fungsi ini menggabungkan akumulator dengan hasil elemen yang dipetakanSecara intuitif,
mapReduce
buat peredam baru yang bisa kita pasang langsungArray.prototype.reduce
. Tetapi yang lebih penting, kita dapat mengimplementasikan implementasi functor objek kita secaraomap
jelas dengan memanfaatkan objek monoid,Object.assign
dan{}
.Perhatikan bahwa satu-satunya bagian dari program yang harus kami tulis adalah implementasi pemetaan itu sendiri -
Yang mengatakan, diberi objek yang diketahui
o
dan beberapa kuncik
, membangun objek dan yang properti yang dihitungk
adalah hasil dari memanggilf
nilai kuncio[k]
,.Kita mendapatkan sekilas
mapReduce
potensi sequencing jika kita abstrak terlebih dahuluoreduce
Semuanya berfungsi sama, tetapi sekarang
omap
dapat didefinisikan pada tingkat yang lebih tinggi. Tentu saja yang baruObject.entries
membuat ini terlihat konyol, tetapi latihan ini tetap penting bagi pelajar.Anda tidak akan melihat potensi penuh dari
mapReduce
sini, tetapi saya membagikan jawaban ini karena menarik untuk melihat berapa banyak tempat yang dapat diterapkan. Jika Anda tertarik pada bagaimana ini diturunkan dan cara lain itu bisa berguna, silakan lihat jawaban ini .sumber
Map
danMap.entries
, OK: D. Saya bosan menyalahgunakan objek biasa sebagai tipe data peta.Map
harus digunakan di mana / bila mungkin, tetapi itu tidak sepenuhnya menggantikan kebutuhan untuk menggunakan prosedur ini pada objek JS biasa tho: DBerdasarkan jawaban @Amberlamps, inilah fungsi utilitas (sebagai komentar itu terlihat jelek)
dan penggunaannya adalah:
sumber
sumber
enumerable
defaultsfalse
Respons saya sebagian besar didasarkan pada respons berperingkat tertinggi di sini dan mudah-mudahan semua orang mengerti (juga memiliki penjelasan yang sama pada GitHub saya). Inilah mengapa penerapannya pada peta bekerja:
Tujuan dari fungsi ini adalah untuk mengambil objek dan memodifikasi konten asli objek menggunakan metode yang tersedia untuk semua objek (objek dan array sama) tanpa mengembalikan array. Hampir semua yang ada di dalam JS adalah objek, dan untuk alasan itu, elemen-elemen yang lebih jauh di dalam pipa pewarisan berpotensi dapat secara teknis menggunakan yang tersedia untuk yang berada di garis atas (dan sebaliknya muncul).
Alasan bahwa ini berfungsi adalah karena fungsi .map mengembalikan array yang MEMBUTUHKAN bahwa Anda memberikan PENGEMBALIAN array secara eksplisit atau implisit alih-alih hanya memodifikasi objek yang ada. Anda pada dasarnya mengelabui program untuk berpikir objek adalah array dengan menggunakan Object.keys yang akan memungkinkan Anda untuk menggunakan fungsi peta dengan aktingnya pada nilai-nilai yang terkait dengan kunci individu (saya sebenarnya secara tidak sengaja mengembalikan array tetapi memperbaikinya). Selama tidak ada pengembalian dalam arti normal, tidak akan ada array yang dibuat dengan objek asli masih utuh dan dimodifikasi seperti yang diprogram.
Program khusus ini mengambil objek yang disebut gambar dan mengambil nilai kunci dan menambahkan tag url untuk digunakan dalam fungsi lain. Asli adalah ini:
... dan dimodifikasi adalah ini:
Struktur asli objek dibiarkan utuh memungkinkan untuk akses properti normal selama tidak ada pengembalian. JANGAN memilikinya mengembalikan array seperti biasa dan semuanya akan baik-baik saja. Tujuannya adalah MENGUBAH nilai-nilai asli (gambar [kunci]) untuk apa yang diinginkan dan bukan yang lain. Sejauh yang saya tahu, untuk mencegah output array TELAH ada REASSIGNMENT gambar [kunci] dan tidak ada permintaan implisit atau eksplisit untuk mengembalikan array (tugas variabel melakukan ini dan glitching bolak-balik untuk saya).
EDIT:
Pergi ke alamat metode lain mengenai penciptaan objek baru untuk menghindari memodifikasi objek asli (dan penugasan ulang tampaknya masih diperlukan untuk menghindari sengaja membuat array sebagai output). Fungsi-fungsi ini menggunakan sintaks panah dan jika Anda hanya ingin membuat objek baru untuk digunakan di masa depan.
Cara kerja fungsi-fungsi ini adalah seperti ini:
mapFn mengambil fungsi untuk ditambahkan nanti (dalam hal ini (nilai) => nilai) dan hanya mengembalikan apa pun yang disimpan di sana sebagai nilai untuk kunci itu (atau dikalikan dua jika Anda mengubah nilai kembali seperti yang dilakukannya) di mapFn ( obj) [key],
dan kemudian mendefinisikan kembali nilai asli yang terkait dengan kunci dalam hasil [key] = mapFn (obj) [key]
dan mengembalikan operasi yang dilakukan pada hasil (akumulator yang terletak di kurung dimulai pada akhir fungsi .reduce).
Semua ini dilakukan pada objek yang dipilih dan MASIH di sana TIDAK BISA menjadi permintaan implisit untuk array yang dikembalikan dan hanya berfungsi ketika menetapkan ulang nilai sejauh yang saya tahu. Ini membutuhkan beberapa senam mental tetapi mengurangi garis kode yang diperlukan seperti yang dapat dilihat di atas. Output persis sama seperti yang bisa dilihat di bawah ini:
Ingat ini bekerja dengan NON-NUMBERS. Anda BISA menduplikasi objek APAPUN dengan SIMPLY MENGEMBALIKAN NILAI di fungsi mapFN.
sumber
Fungsi pertama menjawab pertanyaan itu. Itu menciptakan peta.
Fungsi kedua tidak membuat peta. Alih-alih, itu loop melalui properti di objek yang ada menggunakan
hasOwnProperty()
. Alternatif peta ini mungkin merupakan solusi yang lebih baik dalam beberapa situasi.sumber
Jika Anda tertarik untuk melakukan
map
ping tidak hanya nilai tetapi juga kunci, saya telah menulisObject.map(valueMapper, keyMapper)
, yang berlaku seperti ini:sumber
npm install @mattisg/object.map
.Saya membutuhkan versi yang memungkinkan memodifikasi kunci juga (berdasarkan jawaban @Amberlamps dan @yonatanmn);
factObject =
Sunting: sedikit perubahan untuk melewati objek awal {}. Mengizinkannya menjadi [] (jika kunci bilangan bulat)
sumber
Saya secara khusus ingin menggunakan fungsi yang sama yang saya gunakan untuk array untuk objek tunggal, dan ingin membuatnya tetap sederhana. Ini bekerja untuk saya:
sumber
var mapped = myMapFunction(item)
Untuk merespons lebih dekat dengan apa tepatnya yang diminta OP, OP menginginkan objek:
untuk memiliki metode peta
myObject.map
,Jawaban imho terbaik (diukur dengan istilah " mendekati apa yang diminta " + "tidak ada ES {5,6,7} diperlukan tanpa perlu") adalah:
Kode di atas menghindari sengaja menggunakan fitur bahasa apa pun, hanya tersedia dalam edisi ECMAScript terbaru. Dengan kode di atas masalah bisa diselesaikan seperti ini:
Selain disukai oleh beberapa orang, itu akan menjadi kemungkinan untuk memasukkan solusi dalam rantai prototipe seperti ini.
Sesuatu, yang ketika dilakukan dengan pengawasan yang cermat seharusnya tidak memiliki efek buruk dan tidak mempengaruhi
map
metode objek lain (yaitu Array'smap
).sumber
Pertama, konversi HTMLCollection Anda menggunakan Object.entries (koleksi). Maka itu adalah iterable sekarang Anda dapat menggunakan metode .map di atasnya.
referensi https://medium.com/@js_tut/calling-javascript-code-on-multiple-div-elements-without-the-id-attribute-97ff6a50f31
sumber
Tentukan fungsi mapEntries.
mapEntries mengambil fungsi callback yang dipanggil pada setiap entri di objek dengan nilai parameter, kunci dan objek. Itu harus mengembalikan nilai baru.
mapEntries harus mengembalikan objek baru dengan nilai baru yang dikembalikan dari callback.
Sunting: Versi sebelumnya tidak menentukan bahwa ini bukan properti enumerable
sumber
Hei menulis fungsi mapper kecil yang mungkin bisa membantu.
sumber
Pandangan yang berbeda untuk itu adalah menggunakan fungsi string json kustom yang juga dapat bekerja pada objek yang dalam. Ini mungkin berguna jika Anda bermaksud mempostingnya ke server sebagai json
sumber
Saya hanya menangani string untuk mengurangi pengecualian:
sumber
Object Mapper dalam TypeScript
Saya suka contoh yang digunakan
Object.fromEntries
seperti ini , tapi tetap saja, mereka tidak mudah digunakan. Jawaban yang menggunakanObject.keys
dan kemudian mencarikey
sebenarnya melakukan beberapa pencarian yang mungkin tidak diperlukan.Saya berharap ada
Object.map
fungsi, tetapi kita dapat membuatnya sendiri dan menyebutnyaobjectMap
dengan kemampuan untuk memodifikasi keduanyakey
danvalue
:Penggunaan (JavaScript):
Kode (TypeScript):
Jika Anda tidak menggunakan TypeScript maka salin kode di atas di TypeScript Playground untuk mendapatkan kode JavaScript.
Juga, alasan saya memasukkan
keySelector
setelahvalSelector
dalam daftar parameter, adalah karena itu opsional.* Beberapa pujian untuk jawaban pabrik alexander .
sumber
Fungsi ini berjalan secara rekursif melalui objek dan array objek. Atribut dapat dihapus jika dikembalikan tidak terdefinisi
sumber