Saya memiliki struktur data bersarang yang berisi objek dan array. Bagaimana saya bisa mengekstrak informasi, yaitu mengakses nilai (atau kunci) tertentu atau beberapa?
Sebagai contoh:
var data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
Bagaimana saya bisa mengakses name
item kedua di items
?
javascript
arrays
object
nested
data-manipulation
Felix Kling
sumber
sumber
Jawaban:
Persiapan
JavaScript hanya memiliki satu tipe data yang dapat berisi banyak nilai: Objek . Sebuah Array adalah bentuk khusus dari objek.
(Biasa) Objek memiliki bentuk
Array memiliki formulir
Baik array dan objek memperlihatkan
key -> value
struktur. Kunci dalam array harus berupa angka, sedangkan string apa pun dapat digunakan sebagai kunci dalam objek. Pasangan kunci-nilai juga disebut "properti" .Properti dapat diakses menggunakan notasi titik
atau notasi braket , jika nama properti tidak akan menjadi nama pengidentifikasi JavaScript yang valid [spec] , atau namanya adalah nilai dari variabel:
Karena alasan itu, elemen array hanya dapat diakses menggunakan notasi braket:
Tunggu ... bagaimana dengan JSON?
JSON adalah representasi data tekstual, seperti XML, YAML, CSV, dan lainnya. Untuk bekerja dengan data tersebut, pertama-tama harus dikonversi ke tipe data JavaScript, yaitu array dan objek (dan cara bekerja dengan itu baru saja dijelaskan). Bagaimana cara menguraikan JSON dijelaskan dalam pertanyaan Parse JSON dalam JavaScript? .
Bahan bacaan lebih lanjut
Cara mengakses array dan objek adalah pengetahuan JavaScript yang mendasar dan oleh karena itu disarankan untuk membaca Panduan JavaScript MDN , terutama bagian-bagiannya
Mengakses struktur data bersarang
Struktur data bersarang adalah array atau objek yang merujuk ke array atau objek lain, yaitu nilainya adalah array atau objek. Struktur tersebut dapat diakses dengan menerapkan notasi titik atau braket secara berurutan.
Berikut ini sebuah contoh:
Mari kita asumsikan kita ingin mengakses
name
item kedua.Inilah cara kita melakukannya langkah demi langkah:
Seperti yang dapat kita lihat
data
adalah objek, maka kita dapat mengakses propertinya menggunakan notasi titik. Theitems
properti diakses sebagai berikut:Nilainya adalah sebuah array, untuk mengakses elemen keduanya, kita harus menggunakan notasi braket:
Nilai ini adalah objek dan kami menggunakan notasi titik lagi untuk mengakses
name
properti. Jadi kami akhirnya mendapatkan:Atau, kami dapat menggunakan notasi braket untuk salah satu properti, terutama jika nama tersebut mengandung karakter yang membuatnya tidak valid untuk penggunaan notasi titik:
Saya mencoba mengakses properti tetapi saya hanya mendapatkan
undefined
kembali?Sebagian besar waktu ketika Anda mendapatkan
undefined
, objek / array tidak memiliki properti dengan nama itu.Gunakan
console.log
atauconsole.dir
dan periksa struktur objek / array. Properti yang Anda coba akses mungkin sebenarnya ditentukan pada objek / array bersarang.Bagaimana jika nama properti dinamis dan saya tidak mengetahuinya sebelumnya?
Jika nama properti tidak diketahui atau kami ingin mengakses semua properti dari suatu objek / elemen array, kita dapat menggunakan loop
for...in
[MDN] untuk objek dan loopfor
[MDN] untuk array untuk beralih ke semua properti / elemen.Benda
Untuk mengulangi semua properti dari
data
, kita dapat beralih di atas objek seperti:Bergantung pada dari mana objek itu berasal (dan apa yang ingin Anda lakukan), Anda mungkin harus menguji di setiap iterasi apakah properti itu benar-benar properti objek, atau properti warisan. Anda dapat melakukan ini dengan
Object#hasOwnProperty
[MDN] .Sebagai alternatif
for...in
denganhasOwnProperty
, Anda dapat menggunakanObject.keys
[MDN] untuk mendapatkan berbagai nama properti :Array
Untuk beralih ke semua elemen
data.items
array , kami menggunakanfor
loop:Kita juga bisa menggunakannya
for...in
untuk beralih pada array, tetapi ada alasan mengapa ini harus dihindari: Mengapa 'untuk (item dalam daftar)' dengan array dianggap praktik yang buruk dalam JavaScript? .Dengan meningkatnya dukungan browser dari ECMAScript 5, metode array
forEach
[MDN] juga menjadi alternatif yang menarik:Dalam lingkungan yang mendukung ES2015 (ES6), Anda juga dapat menggunakan loop [MDN] , yang tidak hanya berfungsi untuk array, tetapi untuk semua iterable :
for...of
Dalam setiap iterasi,
for...of
secara langsung memberi kita elemen iterable berikutnya, tidak ada "indeks" untuk diakses atau digunakan.Bagaimana jika "kedalaman" struktur data tidak saya ketahui?
Selain kunci yang tidak dikenal, "kedalaman" dari struktur data (yaitu berapa banyak objek bersarang) yang dimilikinya, mungkin juga tidak diketahui. Cara mengakses properti yang sangat bersarang biasanya tergantung pada struktur data yang tepat.
Tetapi jika struktur data berisi pola berulang, misalnya representasi pohon biner, solusinya biasanya mencakup [Wikipedia] secara rekursif mengakses setiap tingkat struktur data.
Berikut adalah contoh untuk mendapatkan simpul daun pertama dari pohon biner:
Tampilkan cuplikan kode
Cara yang lebih umum untuk mengakses struktur data bersarang dengan kunci dan kedalaman yang tidak dikenal adalah dengan menguji jenis nilai dan bertindak sesuai.
Berikut adalah contoh yang menambahkan semua nilai primitif di dalam struktur data bersarang ke dalam array (dengan asumsi itu tidak mengandung fungsi apa pun). Jika kita menemukan objek (atau array), kita cukup memanggil
toArray
lagi pada nilai itu (panggilan rekursif).Tampilkan cuplikan kode
Pembantu
Karena struktur objek atau array yang kompleks belum tentu jelas, kita dapat memeriksa nilai pada setiap langkah untuk memutuskan bagaimana bergerak lebih jauh.
console.log
[MDN] danconsole.dir
[MDN] membantu kami melakukan ini. Misalnya (output dari konsol Chrome):Di sini kita melihat bahwa itu
data.items
adalah array dengan dua elemen yang keduanya objek. Di konsol Chrome objek bahkan dapat diperluas dan diperiksa segera.Ini memberi tahu kita bahwa itu
data.items[1]
adalah objek, dan setelah meluaskannya kita melihat bahwa ia memiliki tiga propertiid
,,name
dan__proto__
. Yang terakhir adalah properti internal yang digunakan untuk rantai prototipe objek. Rantai prototipe dan warisan tidak termasuk dalam cakupan untuk jawaban ini.sumber
let object = {a: 1, b: 2, c: { a: 3, b: 4 }};
, ini mengembalikan array yang berisi array untuk setiap objek bersarang, dalam hal ini[ 1, 2, [ 3, 4 ] ]
Bukankah lebih baik menggunakan concat dalam panggilan rekursif alih-alih mendorong? (membutuhkan hasil yang dapat diubah)Anda dapat mengaksesnya dengan cara ini
atau
Kedua cara itu sama.
sumber
Jika Anda mencoba mengakses
item
struktur contoh denganid
atauname
, tanpa mengetahui posisinya di dalam array, cara termudah untuk melakukannya adalah dengan menggunakan pustaka underscore.js :Dari pengalaman saya, menggunakan fungsi urutan yang lebih tinggi daripada
for
ataufor..in
loop menghasilkan kode yang lebih mudah untuk dipikirkan, dan karenanya lebih dapat dipertahankan.Hanya 2 sen saya.
sumber
Objek dan array memiliki banyak metode bawaan yang dapat membantu Anda dalam memproses data.
Catatan: dalam banyak contoh saya menggunakan fungsi panah . Mereka mirip dengan ekspresi fungsi , tetapi mereka mengikat
this
nilai secara leksikal.Object.keys()
,Object.values()
(ES 2017) danObject.entries()
(ES 2017)Object.keys()
mengembalikan array kunci objek,Object.values()
mengembalikan array nilai objek, danObject.entries()
mengembalikan array kunci objek dan nilai yang sesuai dalam suatu format[key, value]
.Object.entries()
dengan for-of loop dan penugasan penugasanSangat mudah untuk mengulangi hasil
Object.entries()
dengan for-of loop dan tugas penataan .For-of loop memungkinkan Anda mengulangi elemen array. Sintaksnya adalah
for (const element of array)
(kita dapat mengganticonst
denganvar
ataulet
, tetapi lebih baik digunakanconst
jika kita tidak ingin memodifikasielement
).Merusak penugasan memungkinkan Anda mengekstrak nilai dari array atau objek dan menetapkannya ke variabel. Dalam hal ini
const [key, value]
berarti bahwa alih-alih menugaskan[key, value]
arrayelement
, kami menetapkan elemen pertama array itukey
dan elemen keduavalue
. Ini setara dengan ini:Seperti yang Anda lihat, perusakan membuat ini lebih sederhana.
Array.prototype.every()
danArray.prototype.some()
The
every()
kembali metodetrue
jika fungsi callback pengembalian yang ditentukantrue
untuk setiap elemen array. Thesome()
kembali metodetrue
jika fungsi callback tertentu kembalitrue
untuk beberapa (setidaknya satu) elemen.Array.prototype.find()
danArray.prototype.filter()
The
find()
metode mengembalikan pertama unsur yang memenuhi fungsi callback yang disediakan. Thefilter()
Metode mengembalikan array semua elemen yang memenuhi fungsi callback yang disediakan.Array.prototype.map()
The
map()
Metode mengembalikan array dengan hasil memanggil fungsi callback disediakan di elemen array.Array.prototype.reduce()
The
reduce()
Metode mengurangi array untuk nilai tunggal dengan memanggil fungsi callback yang disediakan dengan dua elemen.The
reduce()
Metode mengambil parameter opsional kedua, yang merupakan nilai awal. Ini berguna ketika array yang Anda panggilreduce()
dapat memiliki nol atau satu elemen. Misalnya, jika kita ingin membuat fungsisum()
yang menggunakan array sebagai argumen dan mengembalikan jumlah semua elemen, kita bisa menulisnya seperti itu:sumber
Object.keys(data["items"]).forEach(function(key) { console.log(data["items"][key].id); console.log(data["items"][key].name); });
Kadang-kadang, mengakses objek bersarang menggunakan string dapat diinginkan. Pendekatan sederhana adalah tingkat pertama, misalnya
Tapi ini sering tidak terjadi dengan json kompleks. Ketika json menjadi lebih kompleks, pendekatan untuk menemukan nilai-nilai di dalam json juga menjadi kompleks. Pendekatan rekursif untuk menavigasi json adalah yang terbaik, dan bagaimana rekursi itu dimanfaatkan akan tergantung pada jenis data yang dicari. Jika ada pernyataan kondisional yang terlibat, pencarian json bisa menjadi alat yang baik untuk digunakan.
Jika properti yang diakses sudah diketahui, tetapi jalurnya kompleks, misalnya dalam objek ini
Dan Anda tahu Anda ingin mendapatkan hasil pertama dari array di objek, mungkin Anda ingin menggunakannya
Namun, itu akan menyebabkan pengecualian karena tidak ada properti objek dengan nama itu. Solusi untuk dapat menggunakan ini adalah dengan meratakan aspek pohon objek. Ini dapat dilakukan secara rekursif.
Sekarang, objek yang kompleks dapat diratakan
Ini adalah salah
jsFiddle Demo
satu pendekatan yang digunakan.sumber
obj["arr[0].name"]
bukanobj.arr[0].name
? Anda tidak perlu / ingin berurusan dengan objek yang rata kecuali untuk serialisasi.Pertanyaan ini cukup lama, sehingga merupakan pembaruan kontemporer. Dengan dimulainya ES2015 ada alternatif untuk mendapatkan data yang Anda butuhkan. Sekarang ada fitur yang disebut destruksi objek untuk mengakses objek bersarang.
Contoh di atas membuat variabel yang dipanggil
secondName
dariname
kunci dari array yang disebutitems
,,
kata kesepian melewati objek pertama dalam array.Khususnya mungkin berlebihan untuk contoh ini, karena akses array sederhana lebih mudah dibaca, tetapi berguna saat memecah objek secara umum.
Ini adalah pengantar yang sangat singkat untuk kasus penggunaan khusus Anda, perusakan dapat menjadi sintaks yang tidak biasa untuk digunakan pada awalnya. Saya akan merekomendasikan membaca dokumentasi Mozilla's Destructure Assignment untuk mempelajari lebih lanjut.
sumber
Untuk mengakses atribut bersarang, Anda perlu menentukan namanya dan kemudian mencari melalui objek.
Jika Anda sudah tahu path yang tepat, maka Anda bisa membuat hardcode di skrip Anda seperti:
ini juga bekerja -
Ketika Anda tidak tahu nama persisnya sebelumnya, atau pengguna adalah orang yang memberikan nama untuk Anda. Maka pencarian secara dinamis melalui struktur data diperlukan. Beberapa menyarankan di sini bahwa pencarian dapat dilakukan menggunakan
for
loop, tetapi ada cara yang sangat sederhana untuk melintasi jalur menggunakanArray.reduce
.Path adalah cara untuk mengatakan: Pertama ambil objek dengan kunci
items
, yang kebetulan berupa array. Kemudian ambil1
elemen -st (array indeks 0). Terakhir ambil objek dengan kunciname
dalam elemen array itu, yang merupakan stringbar
.Jika Anda memiliki jalan yang sangat panjang, Anda bahkan dapat menggunakan
String.split
untuk mempermudah semua ini -Ini hanyalah JavaScript biasa, tanpa menggunakan perpustakaan pihak ketiga seperti jQuery atau lodash.
sumber
atau
Pada dasarnya, gunakan titik di antara setiap keturunan yang terungkap di bawahnya dan ketika Anda memiliki nama objek yang terbuat dari dua string, Anda harus menggunakan notasi ["Object Name"]. Kalau tidak, cukup satu titik saja sudah cukup;
Sumber: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-objects
untuk menambah ini, mengakses Array bersarang akan terjadi seperti:
Sumber: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays/
Dokumen lain yang lebih bermanfaat menggambarkan situasi di atas: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#Bracket_notation
Akses properti melalui dot walking: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation
sumber
Anda bisa menggunakan
lodash _get
fungsi:sumber
Menggunakan JSONPath akan menjadi salah satu solusi paling fleksibel jika Anda bersedia menyertakan perpustakaan: https://github.com/s3u/JSONPath (node dan browser)
Untuk kasus penggunaan Anda, json path adalah:
begitu:
sumber
Untuk jaga-jaga, siapa pun yang mengunjungi pertanyaan ini pada 2017 atau lebih baru dan mencari cara yang mudah diingat , berikut ini adalah posting blog yang rumit tentang Mengakses Objek Bersarang di JavaScript tanpa dikacaukan oleh
Tidak dapat membaca properti 'foo' dari kesalahan yang tidak terdefinisi
1. Pola akses objek bersarang Oliver Steele
Cara termudah dan terbersih adalah dengan menggunakan pola akses objek bersarang Oliver Steele
Dengan notasi ini, Anda tidak akan pernah bertemu
Tidak dapat membaca properti 'nama' yang tidak terdefinisi .
Anda pada dasarnya memeriksa apakah pengguna ada, jika tidak, Anda membuat objek kosong dengan cepat. Dengan cara ini, kunci level berikutnya akan selalu diakses dari objek yang ada atau objek kosong , tetapi tidak pernah dari yang tidak ditentukan.
2. Akses Objek Bersarang Menggunakan Array Reduce
Untuk dapat mengakses array bersarang, Anda dapat menulis util pengurangan array Anda sendiri.
Ada juga jenis penanganan perpustakaan typy yang sangat baik yang melakukan semua ini untuk Anda.
sumber
((user || {}).address || new Array(3))[1].name
...[1].bar
akan menghasilkan kesalahan jika elemen1
tidak ada. Tapi itu juga terjadi....foo.bar
jikafoo
tidak ada. Anda harus "menjaga" akses1
juga, sama seperti Anda "menjaga" akses properti lainnya. Array hanyalah sebuah objek. "Elemen array" hanyalah sebuah properti. Diterapkan dengan benar akan(((user || {}).address || {})[1] || {}).name
.Saya lebih suka JQuery. Lebih bersih dan mudah dibaca.
sumber
Mengakses objek multi level secara dinamis.
Biola yang berfungsi: https://jsfiddle.net/andreitodorut/3mws3kjL/
sumber
Jika Anda mencari satu atau lebih objek yang memenuhi kriteria tertentu, Anda memiliki beberapa opsi menggunakan query-js
Ada juga
single
dansingleOrDefault
mereka bekerja sangat sukafirst
danfirstOrDefault
masing - masing. Satu-satunya perbedaan adalah bahwa mereka akan melempar jika lebih dari satu pertandingan ditemukan.untuk penjelasan lebih lanjut tentang query-js Anda bisa mulai dengan posting ini
sumber
The Underscore js Way
Yang merupakan pustaka JavaScript yang menyediakan seluruh
functional programming
bantuan yang bermanfaat tanpa perlu memperluas objek bawaan.Larutan:
sumber
Pertanyaan lama tetapi karena tidak ada yang menyebutkan lodash (hanya garis bawah).
Jika Anda sudah menggunakan lodash di proyek Anda, saya pikir cara yang elegan untuk melakukan ini dalam contoh kompleks:
Memilih 1
sama dengan:
Memilih 2
Perbedaan antara opsi pertama dan kedua adalah bahwa di Opt 1 jika Anda memiliki salah satu properti yang hilang (tidak terdefinisi) di jalan Anda tidak mendapatkan kesalahan, itu mengembalikan Anda parameter ketiga.
Untuk filter array lodash memiliki
_.find()
tetapi saya lebih suka menggunakan biasafilter()
. Tapi saya masih berpikir metode di atas_.get()
sangat berguna ketika bekerja dengan data yang sangat kompleks. Saya menghadapi API yang benar-benar kompleks di masa lalu dan itu berguna!Saya harap ini dapat bermanfaat bagi siapa yang mencari opsi untuk memanipulasi data yang sangat rumit yang tersirat pada judulnya.
sumber
Saya tidak berpikir penanya hanya menyangkut objek bertingkat satu level, jadi saya menyajikan demo berikut untuk menunjukkan cara mengakses node objek json yang sangat bersarang. Baiklah, mari cari node dengan id '5'.
sumber
Anda dapat menggunakan sintaks
jsonObject.key
untuk mengakses nilai. Dan jika Anda ingin mengakses nilai dari array, maka Anda bisa menggunakan sintaksjsonObjectArray[index].key
.Berikut adalah contoh kode untuk mengakses berbagai nilai untuk memberi Anda ide.
sumber
Pendekatan dinamis
Dalam
deep(data,key)
fungsi di bawah ini , Anda dapat menggunakankey
string arbitrer - dalam kasusitems[1].name
Anda (Anda dapat menggunakan notasi array[i]
di level apa pun) - jika kunci tidak valid maka undefined adalah return.Tampilkan cuplikan kode
sumber
Pendekatan pythonic, rekursif dan fungsional untuk mengurai pohon JSON sewenang-wenang:
di mana data adalah daftar python (diurai dari string teks JSON):
sumber
Fungsi grep jQuery memungkinkan Anda memfilter array:
sumber
sumber
Pada tahun 2020, Anda dapat menggunakan @ babel / plugin-proposal-opsional-chaining. Sangat mudah untuk mengakses nilai yang bersarang di suatu objek.
https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining
https://github.com/tc39/proposal-optional-chaining
sumber
Saya
stringdata
berasal dari file PHP tetapi masih, saya tunjukkan di sini divar
. Ketika saya langsung mengambil json saya keobj
dalamnya tidak akan menunjukkan itu sebabnya saya meletakkan file json saya sebagaivar obj=JSON.parse(stringdata);
jadi setelah itu saya mendapatkanmessage
obj dan ditampilkan di kotak peringatan kemudian saya dapatkandata
yang merupakan json array dan menyimpannya dalam satu variabelArrObj
kemudian saya membaca objek pertama dari array itu dengan nilai kunci seperti iniArrObj[0].id
sumber
stringjson
bukan string.Menggunakan lodash akan menjadi solusi yang baik
Ex:
sumber