Andrew: Saya memanggil API dan di JSON saya mendapatkan kembali, jika ada banyak hasil saya mendapatkan Array tetapi jika hanya ada satu saya mendapatkan Hash daripada satu elemen Array. Apakah ada penyerang yang lebih baik daripada melakukan pemeriksaan Array vs Hash?
drhyde
2
Jadi, Anda mendapatkan salah satunya [result_hash, another_result_hash]atau single_result_hash? Siapa pun yang membuat API itu tidak melakukan pekerjaan dengan baik!
Andrew Grimm
2
Anda benar, Andrew, dan saya yakin jauh lebih mudah untuk membuat orang yang menulis API memperbaikinya daripada menguji hash versus array.
Olivier 'Ölbaum' Scherler
Saya memiliki situasi yang sama dengan @drhyde. Dalam kasus saya, pihak ke-3 adalah HTTParty yang setelah mengurai file XML tidak memiliki cara untuk memutuskan apa cara terbaik untuk menangani situasi di mana suatu elemen dapat memiliki anak 1-n.
Perlu dicatat bahwa "is_a?" metode ini benar jika kelas berada di mana saja di pohon leluhur objek. contohnya:
@some_var.is_a?(Object) # => true
hal di atas benar jika @some_var adalah turunan dari hash atau kelas lain yang berasal dari Object. Jadi, jika Anda ingin pencocokan ketat pada jenis kelas, gunakan == atau instance_of? Metode mungkin adalah apa yang Anda cari.
is_a?adalah pilihan terbaik, karena ia juga mengembalikan truesubclass.
Fábio Batista
Dan, tentu saja, Anda juga mengabaikan tanda kurung, jadi @som_var.is_a? Hashbekerja juga :)
Gus Shortz
7
Hati-hati, ini benar-benar bisa mengacaukan Anda jika seseorang akhirnya memberikan Anda contoh ActiveSupport :: HashWithIndifferentAccess. Yang merespons seperti hash, tetapi sebenarnya bukan hash. :(
unflores
Saya juga ingin lebih banyak jawaban yang merinci tentang mengetik bebek, karena penulis asli tampaknya sedang mencari cara ruby untuk melakukan pemeriksaan jenis.
NobodysNightmare
3
@unflores ActiveSupport::HashWithIndifferentAccessmewarisi dari Hash, karenanya @some_var.is_a?(Hash)akan mengembalikan true dalam kasus ini juga. (Saya baru saja memiliki pertanyaan yang sama dan kasus HashWithIndifferentAccess dan agak bingung dengan komentar Anda ... jadi saya ingin mengklarifikasi)
Stilzk1n
38
Pertama-tama, jawaban terbaik untuk pertanyaan literal adalah
Hash === @some_var
Tetapi pertanyaan itu seharusnya dijawab dengan menunjukkan bagaimana melakukan bebek-mengetik di sini. Itu tergantung sedikit pada jenis bebek yang Anda butuhkan.
Biasanya di ruby ketika Anda mencari "tipe" Anda sebenarnya menginginkan "tipe bebek" atau "apakah dukun seperti bebek?". Anda akan melihat apakah itu menanggapi metode tertentu:
@some_var.respond_to?(:each)
Anda dapat mengulangi @some_var karena merespons: masing-masing
Jika Anda benar-benar ingin mengetahui jenisnya dan jika itu adalah Hash atau Array maka Anda dapat melakukan:
["Hash", "Array"].include?(@some_var.class) #=> check both through instance class
@some_var.kind_of?(Hash) #=> to check each at once
@some_var.is_a?(Array) #=> same as kind_of
Ini tidak akan berfungsi jika kode Anda bergantung pada urutan data (misalnya jika Anda menggunakan each_with_index). Urutan elemen diimplementasikan secara berbeda antara hash dan array dan berbeda antara versi ruby (. Intertwingly.net/slides/2008/oscon/ruby19/22 )
juan2raid
1
@ juan2raid: Jika urutan itu penting, panggil sortdulu.
Andrew Grimm
Contoh kedua @Brandon harus mengonversi kelas menjadi string. <br/>["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
Dalam praktiknya, Anda akan sering ingin bertindak berbeda tergantung pada apakah variabel itu Array atau Hash, bukan hanya sekadar memberi tahu. Dalam situasi ini, idiom elegan adalah sebagai berikut:
case item
when Array
#do somethingwhen Hash
#do something elseend
Perhatikan bahwa Anda tidak mengaktifkan .classmetode ini item.
Perhatikan bahwa ini tidak berfungsi untuk subclass ! Misalnya, jika Anda memiliki ActiveRecord::Collectiondan mencoba instance_of?(Array)maka ini akan kembali false, sedangkan is_a?(Array)akan kembali true.
Tom Lord
0
Jika Anda ingin menguji apakah suatu objek secara ketat atau meluas Hash, gunakan:
value = {}
value.is_a?(Hash) || value.is_a?(Array) #=> true
Tetapi untuk membuat nilai dari mengetik bebek Ruby, Anda bisa melakukan sesuatu seperti:
value = {}
value.respond_to?(:[]) #=> true
Ini berguna ketika Anda hanya ingin mengakses beberapa nilai menggunakan value[:key]sintaks.
Harap dicatat bahwa Array.new["key"]akan memunculkan a TypeError.
[result_hash, another_result_hash]
atausingle_result_hash
? Siapa pun yang membuat API itu tidak melakukan pekerjaan dengan baik!Jawaban:
Anda bisa melakukan:
@some_var.class == Hash
atau juga sesuatu seperti:
Perlu dicatat bahwa "is_a?" metode ini benar jika kelas berada di mana saja di pohon leluhur objek. contohnya:
@some_var.is_a?(Object) # => true
hal di atas benar jika @some_var adalah turunan dari hash atau kelas lain yang berasal dari Object. Jadi, jika Anda ingin pencocokan ketat pada jenis kelas, gunakan == atau instance_of? Metode mungkin adalah apa yang Anda cari.
sumber
is_a?
adalah pilihan terbaik, karena ia juga mengembalikantrue
subclass.@som_var.is_a? Hash
bekerja juga :)ActiveSupport::HashWithIndifferentAccess
mewarisi dari Hash, karenanya@some_var.is_a?(Hash)
akan mengembalikan true dalam kasus ini juga. (Saya baru saja memiliki pertanyaan yang sama dan kasus HashWithIndifferentAccess dan agak bingung dengan komentar Anda ... jadi saya ingin mengklarifikasi)Pertama-tama, jawaban terbaik untuk pertanyaan literal adalah
Tetapi pertanyaan itu seharusnya dijawab dengan menunjukkan bagaimana melakukan bebek-mengetik di sini. Itu tergantung sedikit pada jenis bebek yang Anda butuhkan.
@some_var.respond_to?(:each_pair)
atau
@some_var.respond_to?(:has_key?)
atau bahkan
@some_var.respond_to?(:to_hash)
mungkin benar tergantung aplikasinya.
sumber
Biasanya di ruby ketika Anda mencari "tipe" Anda sebenarnya menginginkan "tipe bebek" atau "apakah dukun seperti bebek?". Anda akan melihat apakah itu menanggapi metode tertentu:
@some_var.respond_to?(:each)
Anda dapat mengulangi @some_var karena merespons: masing-masing
Jika Anda benar-benar ingin mengetahui jenisnya dan jika itu adalah Hash atau Array maka Anda dapat melakukan:
["Hash", "Array"].include?(@some_var.class) #=> check both through instance class @some_var.kind_of?(Hash) #=> to check each at once @some_var.is_a?(Array) #=> same as kind_of
sumber
sort
dulu.["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
Hash === @some_var #=> return Boolean
ini juga dapat digunakan dengan pernyataan kasus
case @some_var when Hash ... when Array ... end
sumber
Saya menggunakan ini:
@var.respond_to?(:keys)
Ini berfungsi untuk Hash dan ActiveSupport :: HashWithIndifferentAccess.
sumber
Dalam praktiknya, Anda akan sering ingin bertindak berbeda tergantung pada apakah variabel itu Array atau Hash, bukan hanya sekadar memberi tahu. Dalam situasi ini, idiom elegan adalah sebagai berikut:
case item when Array #do something when Hash #do something else end
Perhatikan bahwa Anda tidak mengaktifkan
.class
metode iniitem
.sumber
Kamu bisa memakai
instance_of?
misalnya
sumber
ActiveRecord::Collection
dan mencobainstance_of?(Array)
maka ini akan kembalifalse
, sedangkanis_a?(Array)
akan kembalitrue
.Jika Anda ingin menguji apakah suatu objek secara ketat atau meluas
Hash
, gunakan:value = {} value.is_a?(Hash) || value.is_a?(Array) #=> true
Tetapi untuk membuat nilai dari mengetik bebek Ruby, Anda bisa melakukan sesuatu seperti:
value = {} value.respond_to?(:[]) #=> true
Ini berguna ketika Anda hanya ingin mengakses beberapa nilai menggunakan
value[:key]
sintaks.sumber
irb(main):005:0> {}.class => Hash irb(main):006:0> [].class => Array
sumber