วิธีการรับเอาต์พุตเฉพาะการวนซ้ำแฮชใน Ruby


218

ฉันต้องการรับเอาต์พุตเฉพาะการทำซ้ำ Ruby Hash

นี่คือแฮชที่ฉันต้องการทำซ้ำ:

hash = {
  1 => ['a', 'b'], 
  2 => ['c'], 
  3 => ['d', 'e', 'f', 'g'], 
  4 => ['h']
}

นี่คือผลลัพธ์ที่ฉันต้องการได้รับ:

1-----

a

b

2-----

c

3-----

d 

e

f

g

4-----

h

ใน Ruby ฉันจะรับเอาต์พุตดังกล่าวด้วย Hash ของฉันได้อย่างไร


3
หากคุณกำลังทำแฮชซ้ำและคาดว่าจะได้รับคำสั่งคุณอาจต้องใช้คอลเลคชั่นประเภทอื่น
Allen Rice

ฉันสามารถส่งค่าแฮชเป็นตัวเลือกปุ่มตัวเลือกได้หรือไม่?
sts

ฉันกำลังแฮชผ่านเป็นตัวเลือกปุ่มตัวเลือก .. แต่สำหรับตัวเลือกแรกกำลังรับปุ่มตัวเลือกสำหรับค่าอื่น ๆ ที่ฉันไม่ได้รับ
sts

1
@Allen: แฮชได้รับคำสั่งใน Ruby 1.9 Rails ยังมี OrderedHash (ซึ่งใช้เพียงเล็กน้อยเท่านั้น) หากคุณใช้ Ruby <1.9 ดูculann.com/2008/01/rails-goodies-activesupportorderedhash
James A. Rosen

คำตอบ:


323
hash.each do |key, array|
  puts "#{key}-----"
  puts array
end

เกี่ยวกับลำดับที่ฉันควรเพิ่มว่าใน 1.8 รายการจะถูกทำซ้ำในลำดับแบบสุ่ม (ดีจริงตามลำดับที่กำหนดโดยฟังก์ชันการแปลงแป้นพิมพ์ของ Fixnum) ในขณะที่ 1.9 จะถูกทำซ้ำตามลำดับตัวอักษร


1
ที่นี่จะเกิดอะไรขึ้นถ้าไม่มีการใช้รหัสใด ๆ . เราจำเป็นต้องใส่?กุญแจแทน? เช่น: |?, array|ไวยากรณ์นี้ถูกต้องหรือไม่
huzefa biyawarwala

1
@huzefabiyawarwala No ?ไม่ใช่ชื่อตัวแปรที่ถูกต้องใน Ruby คุณสามารถใช้_แต่คุณไม่จำเป็นต้องไป
sepp2k

2
@huzefabiyawarwala ใช่คุณสามารถเขียน|_, v|
sepp2k

1
สิ่งที่ใช้อาร์เรย์ชื่อตัวแปรแทน v หรือค่า?
jrhicks

1
@jrhicks เนื่องจาก OP มีแฮชซึ่งมีค่าเป็นอาร์เรย์
Radon Rosborough

85

วิธีพื้นฐานที่สุดในการวนซ้ำแฮชมีดังนี้:

hash.each do |key, value|
  puts key
  puts value
end

ใช่มันสมเหตุสมผลแล้ว เหตุใดคำตอบของ @ sepp2k จึงมี # {} อยู่บนคีย์
committedandroider

โอ้ไม่เป็นไร ผมเห็นว่ามันเป็นสตริงแก้ไข
committedandroider


18

การเรียงลำดับการแฮชจะแปลงเป็นอาร์เรย์ที่ซ้อนกันแล้วเรียงลำดับตามคีย์ดังนั้นสิ่งที่คุณต้องการคือ:

puts h.sort.map {|k,v| ["#{k}----"] + v}

และถ้าคุณไม่ต้องการส่วน "----" จริง ๆ มันก็แค่:

puts h.sort

ปุ่มแฮชคือตัวเลขดังนั้น '[k + "----"]' จะเพิ่ม TypeError (ไม่สามารถรวมสตริงเข้ากับ Fixnum) คุณต้องการ '[k.to_s + "----"]'
เกล็นแจ็

จริงเพียงพอ ฉันมีตัวอักษรในเวอร์ชันทดสอบ แก้ไขโดยใช้ "# {k} ----" ที่ดียิ่งขึ้น
ล็น mcdonald

10

โซลูชันบรรทัดเดียวของฉัน:

hash.each { |key, array| puts "#{key}-----", array }

ฉันคิดว่ามันอ่านง่ายนะ


1

นอกจากนี้คุณยังสามารถปรับแต่ง Hash::eachเพื่อให้รองรับการแจงนับซ้ำ นี่คือเวอร์ชันของHash::each( Hash::each_pair) ของฉันพร้อมการรองรับบล็อกและตัวแจงนับ :

module HashRecursive
    refine Hash do
        def each(recursive=false, &block)
            if recursive
                Enumerator.new do |yielder|
                    self.map do |key, value|
                        value.each(recursive=true).map{ |key_next, value_next| yielder << [[key, key_next].flatten, value_next] } if value.is_a?(Hash)
                        yielder << [[key], value]
                    end
                end.entries.each(&block)
            else
                super(&block)
            end
        end
        alias_method(:each_pair, :each)
    end
end

using HashRecursive

นี่คือการใช้งานที่เป็นตัวอย่างของการHash::eachที่มีและไม่มีrecursiveธง:

hash = {
    :a => {
        :b => {
            :c => 1,
            :d => [2, 3, 4]
        },
        :e => 5
    },
    :f => 6
}

p hash.each, hash.each {}, hash.each.size
# #<Enumerator: {:a=>{:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}, :f=>6}:each>
# {:a=>{:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}, :f=>6}
# 2

p hash.each(true), hash.each(true) {}, hash.each(true).size
# #<Enumerator: [[[:a, :b, :c], 1], [[:a, :b, :d], [2, 3, 4]], [[:a, :b], {:c=>1, :d=>[2, 3, 4]}], [[:a, :e], 5], [[:a], {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}], [[:f], 6]]:each>
# [[[:a, :b, :c], 1], [[:a, :b, :d], [2, 3, 4]], [[:a, :b], {:c=>1, :d=>[2, 3, 4]}], [[:a, :e], 5], [[:a], {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}], [[:f], 6]]
# 6

hash.each do |key, value|
    puts "#{key} => #{value}"
end
# a => {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}
# f => 6

hash.each(true) do |key, value|
    puts "#{key} => #{value}"
end
# [:a, :b, :c] => 1
# [:a, :b, :d] => [2, 3, 4]
# [:a, :b] => {:c=>1, :d=>[2, 3, 4]}
# [:a, :e] => 5
# [:a] => {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}
# [:f] => 6

hash.each_pair(recursive=true) do |key, value|
    puts "#{key} => #{value}" unless value.is_a?(Hash)
end
# [:a, :b, :c] => 1
# [:a, :b, :d] => [2, 3, 4]
# [:a, :e] => 5
# [:f] => 6

นี่คือตัวอย่างจากคำถามตัวเอง:

hash = {
    1   =>  ["a", "b"], 
    2   =>  ["c"], 
    3   =>  ["a", "d", "f", "g"], 
    4   =>  ["q"]
}

hash.each(recursive=false) do |key, value|
    puts "#{key} => #{value}"
end
# 1 => ["a", "b"]
# 2 => ["c"]
# 3 => ["a", "d", "f", "g"]
# 4 => ["q"]

ดูที่เวอร์ชัน recursive ของHash::merge( Hash::merge!) ที่นี่ด้วย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.