วิธีที่ดีที่สุดในการแปลงอาร์เรย์เป็นแฮชใน Ruby คืออะไร


123

ใน Ruby ได้รับอาร์เรย์ในรูปแบบใดรูปแบบหนึ่งต่อไปนี้ ...

[apple, 1, banana, 2]
[[apple, 1], [banana, 2]]

... อะไรคือวิธีที่ดีที่สุดในการแปลงสิ่งนี้เป็นแฮชในรูปแบบของ ...

{apple => 1, banana => 2}

คำตอบ:


91

หมายเหตุ : สำหรับวิธีแก้ปัญหาที่รัดกุมและมีประสิทธิภาพโปรดดูคำตอบของ Marc-André Lafortuneด้านล่าง

เดิมทีคำตอบนี้ถูกเสนอให้เป็นอีกทางเลือกหนึ่งของแนวทางที่ใช้การแบนซึ่งได้รับการโหวตสูงที่สุดในขณะที่เขียน ฉันควรชี้แจงว่าไม่ได้ตั้งใจจะนำเสนอตัวอย่างนี้เป็นแนวทางปฏิบัติที่ดีที่สุดหรือแนวทางที่มีประสิทธิภาพ คำตอบเดิมมีดังนี้


คำเตือน! การแก้ปัญหาโดยใช้การแบนจะไม่เก็บคีย์หรือค่า Array ไว้!

จากคำตอบยอดนิยมของ @John Topley ลองดู:

a3 = [ ['apple', 1], ['banana', 2], [['orange','seedless'], 3] ]
h3 = Hash[*a3.flatten]

สิ่งนี้ทำให้เกิดข้อผิดพลาด:

ArgumentError: odd number of arguments for Hash
        from (irb):10:in `[]'
        from (irb):10

ตัวสร้างคาดว่าจะมี Array ที่มีความยาวเท่ากัน (เช่น ['k1', 'v1,' k2 ',' v2 ']) สิ่งที่แย่กว่านั้นคือ Array ที่แตกต่างกันซึ่งแบนจนมีความยาวเท่ากันจะทำให้เรามีค่า Hash ที่ไม่ถูกต้อง

หากคุณต้องการใช้คีย์หรือค่า Array คุณสามารถใช้map :

h3 = Hash[a3.map {|key, value| [key, value]}]
puts "h3: #{h3.inspect}"

สิ่งนี้จะเก็บรักษาคีย์ Array:

h3: {["orange", "seedless"]=>3, "apple"=>1, "banana"=>2}

15
นี่เหมือนกับ Hash [a3] เนื่องจาก a3 == a3.map {| k, v | [k, v]} เป็นจริงมันเทียบเท่ากับ a3.dup
คลัสเตอร์

2
แทนที่จะใช้แผนที่ทำไมไม่ระบุความลึกของการแบน? ตัวอย่างเช่นh3 = Hash[*a3.flatten(1)]แทนที่จะh3 = Hash[*a3.flatten]เป็นข้อผิดพลาด
Jeff McCune

3
คำตอบนี้ไม่มีประสิทธิภาพ นอกจากนี้ยังล้าสมัย ดูคำตอบของฉัน
Marc-André Lafortune

1
ใช่ฉันคิดว่าของ Marc-André to_hดีกว่า
B Seven

1
@ Marc-André Lafortune ขอบคุณฉันได้อัปเดตคำตอบเพื่อนำผู้ใช้ไปยังคุณ
สตูว์

145

เพียงแค่ใช้ Hash[*array_variable.flatten]

ตัวอย่างเช่น:

a1 = ['apple', 1, 'banana', 2]
h1 = Hash[*a1.flatten(1)]
puts "h1: #{h1.inspect}"

a2 = [['apple', 1], ['banana', 2]]
h2 = Hash[*a2.flatten(1)]
puts "h2: #{h2.inspect}"

การใช้การArray#flatten(1)จำกัด การเรียกซ้ำเพื่อให้Arrayคีย์และค่าทำงานตามที่คาดไว้


4
โอ้โห! นี่คือเหตุผลที่ฉันรักทับทิม
iGbanam

11
คำเตือน: คำตอบโดยใช้การแบนจะทำให้เกิดปัญหาหากคุณต้องการคีย์อาร์เรย์หรือค่า
สตูว์

ฉันได้โพสต์วิธีแก้ไขทางเลือกด้านล่างซึ่งจะหลีกเลี่ยงปัญหาเกี่ยวกับคีย์หรือค่า Array
สตูว์

5
จะดีกว่าที่จะไม่พยายามและหาวิธีแก้ปัญหาทั้งหมดสำหรับสิ่งนี้ หากคีย์และค่าของคุณจับคู่กันเหมือนใน [[key1, value1], [key2, value2]] ให้ส่งต่อไปยัง Hash [] โดยไม่ต้องขุน แฮช [a2] == แฮช [* a2.flatten] หากอาร์เรย์ถูกแบนอยู่แล้วเช่นใน [key1, value1, key2, value2] ให้นำหน้า var ด้วย *, Hash [* a1]
คลัสเตอร์

8
FWIW หากคุณต้องการ (มากกว่า a) เวอร์ชันเดียวที่เหมาะกับทุกคนคุณสามารถใช้Hash[*ary.flatten(1)]ซึ่งจะเก็บคีย์อาร์เรย์และค่าไว้ มันซ้ำซากflattenที่ทำลายสิ่งเหล่านั้นซึ่งง่ายพอที่จะหลีกเลี่ยง
brymck

81

วิธีที่ดีที่สุดคือใช้Array#to_h:

[ [:apple,1],[:banana,2] ].to_h  #=> {apple: 1, banana: 2}

โปรดทราบว่าto_hยังยอมรับบล็อก:

[:apple, :banana].to_h { |fruit| [fruit, "I like #{fruit}s"] } 
  # => {apple: "I like apples", banana: "I like bananas"}

หมายเหตุ : to_hยอมรับบล็อกใน Ruby 2.6.0+; สำหรับทับทิมต้นคุณสามารถใช้backportsอัญมณีของฉันและrequire 'backports/2.6.0/enumerable/to_h'

to_h ไม่มีบล็อกถูกนำมาใช้ใน Ruby 2.1.0

ก่อน Ruby 2.1 เราสามารถใช้สิ่งที่อ่านได้น้อยกว่าHash[]:

array = [ [:apple,1],[:banana,2] ]
Hash[ array ]  #= > {:apple => 1, :banana => 2}

สุดท้ายระวังวิธีแก้ปัญหาใด ๆ ที่ใช้flattenซึ่งอาจสร้างปัญหากับค่าที่เป็นอาร์เรย์เอง


4
ขอบคุณสำหรับความเรียบง่ายของวิธีการ. to_h ใหม่!
ติดโค้ด

3
ฉันชอบto_hวิธีการนี้ดีกว่าคำตอบข้างต้นเพราะมันแสดงถึงเจตนาของการแปลงหลังจากใช้งานอาร์เรย์
B Seven

1
@BSeven ทั้งArray#to_hมิได้Enumerable#to_hอยู่ในหลักทับทิม 1.9
Iron Savior

จะเกิดอะไรขึ้นถ้าฉันมีอาร์เรย์เป็น[[apple, 1], [banana, 2], [apple, 3], [banana, 4]]และฉันต้องการให้เอาต์พุตเป็น{"apple" =>[1,3], "banana"=>[2,4]}?
nishant

@NishantKumar นั่นเป็นคำถามที่แตกต่างออกไป
Marc-André Lafortune

20

ปรับปรุง

ทับทิม 2.1.0 ถูกปล่อยออกมาในวันนี้ และฉันมาพร้อมกับArray#to_h( บันทึกประจำรุ่นและruby-doc ) ซึ่งช่วยแก้ปัญหาการแปลงไฟล์เป็นArrayไฟล์Hash.

ตัวอย่างเอกสาร Ruby:

[[:foo, :bar], [1, 2]].to_h    # => {:foo => :bar, 1 => 2}

9

แก้ไข: เห็นคำตอบที่โพสต์ในขณะที่ฉันเขียน Hash [a.flatten] ดูเหมือนจะเป็นหนทางไป ต้องพลาดบิตนั้นในเอกสารเมื่อฉันคิดถึงการตอบสนอง คิดว่าโซลูชันที่ฉันเขียนสามารถใช้เป็นทางเลือกอื่นได้หากจำเป็น

รูปแบบที่สองง่ายกว่า:

a = [[:apple, 1], [:banana, 2]]
h = a.inject({}) { |r, i| r[i.first] = i.last; r }

a = array, h = hash, r = return-value hash (อันที่เราสะสม), i = item ในอาร์เรย์

วิธีที่เรียบง่ายที่สุดที่ฉันคิดได้ในการทำรูปแบบแรกมีดังนี้:

a = [:apple, 1, :banana, 2]
h = {}
a.each_slice(2) { |i| h[i.first] = i.last }

2
+1 สำหรับa.inject({})ซับเดียวที่ช่วยให้การกำหนดค่ามีความยืดหยุ่นมากขึ้น
Chris Bloom

นอกจากนี้ยังสามารถวางh = {}จากตัวอย่างที่สองโดยใช้การฉีดลงท้ายด้วยa.each_slice(2).inject({}) { |h,i| h[i.first] = i.last; h }
lindes

คุณทำได้a.each_slice(2).to_h
Conor O'Brien

6

คุณยังสามารถแปลงอาร์เรย์ 2D เป็นแฮชโดยใช้:

1.9.3p362 :005 > a= [[1,2],[3,4]]

 => [[1, 2], [3, 4]]

1.9.3p362 :006 > h = Hash[a]

 => {1=>2, 3=>4} 

4

สรุป & TL; DR:

คำตอบนี้หวังว่าจะเป็นข้อมูลสรุปที่ครอบคลุมจากคำตอบอื่น ๆ

เวอร์ชันที่สั้นมากโดยให้ข้อมูลจากคำถามพร้อมสิ่งพิเศษอีกสองสามข้อ:

flat_array   = [  apple, 1,   banana, 2  ] # count=4
nested_array = [ [apple, 1], [banana, 2] ] # count=2 of count=2 k,v arrays
incomplete_f = [  apple, 1,   banana     ] # count=3 - missing last value
incomplete_n = [ [apple, 1], [banana   ] ] # count=2 of either k or k,v arrays


# there's one option for flat_array:
h1  = Hash[*flat_array]                     # => {apple=>1, banana=>2}

# two options for nested_array:
h2a = nested_array.to_h # since ruby 2.1.0    => {apple=>1, banana=>2}
h2b = Hash[nested_array]                    # => {apple=>1, banana=>2}

# ok if *only* the last value is missing:
h3  = Hash[incomplete_f.each_slice(2).to_a] # => {apple=>1, banana=>nil}
# always ok for k without v in nested array:
h4  = Hash[incomplete_n] # or .to_h           => {apple=>1, banana=>nil}

# as one might expect:
h1 == h2a # => true
h1 == h2b # => true
h1 == h3  # => false
h3 == h4  # => true

การอภิปรายและรายละเอียดเป็นไปตาม


การตั้งค่า: ตัวแปร

เพื่อแสดงข้อมูลที่เราจะใช้ล่วงหน้าฉันจะสร้างตัวแปรบางอย่างเพื่อแสดงถึงความเป็นไปได้ต่างๆของข้อมูล พอดีกับหมวดหมู่ต่อไปนี้:

ขึ้นอยู่กับสิ่งที่อยู่ในคำถามโดยตรงเช่นa1และa2:

(หมายเหตุ: ฉันคิดว่าappleและbananaตั้งใจจะเป็นตัวแทนของตัวแปรอย่างที่คนอื่นทำฉันจะใช้สตริงจากที่นี่เพื่อให้อินพุตและผลลัพธ์ตรงกัน)

a1 = [  'apple', 1 ,  'banana', 2  ] # flat input
a2 = [ ['apple', 1], ['banana', 2] ] # key/value paired input

คีย์และ / หรือค่าหลายค่าเป็นa3:

ในคำตอบอื่น ๆ มีการนำเสนอความเป็นไปได้อื่น ๆ (ซึ่งฉันขยายที่นี่) - คีย์และ / หรือค่าอาจเป็นอาร์เรย์ของตัวเอง:

a3 = [ [ 'apple',                   1   ],
       [ 'banana',                  2   ],
       [ ['orange','seedless'],     3   ],
       [ 'pear',                 [4, 5] ],
     ]

อาร์เรย์ที่ไม่สมดุลเช่นa4:

เพื่อการวัดที่ดีฉันคิดว่าฉันจะเพิ่มหนึ่งรายการสำหรับกรณีที่เราอาจมีข้อมูลที่ป้อนไม่ครบถ้วน:

a4 = [ [ 'apple',                   1],
       [ 'banana',                  2],
       [ ['orange','seedless'],     3],
       [ 'durian'                    ], # a spiky fruit pricks us: no value!
     ]

ตอนนี้ไปทำงาน:

เริ่มต้นด้วยอาร์เรย์แบบแบนเริ่มต้น a1 :

บางคนแนะนำให้ใช้#to_h(ซึ่งปรากฏใน Ruby 2.1.0 และสามารถย้อนกลับไปยังเวอร์ชันก่อนหน้าได้) สำหรับอาร์เรย์แบบแบนเริ่มต้นจะใช้ไม่ได้:

a1.to_h   # => TypeError: wrong element type String at 0 (expected array)

การใช้Hash::[]ร่วมกับตัวดำเนินการ Splatจะ:

Hash[*a1] # => {"apple"=>1, "banana"=>2}

a1เพื่อให้เป็นทางออกสำหรับกรณีที่เรียบง่ายที่แสดงโดย

ด้วยอาร์เรย์ของอาร์เรย์คู่คีย์ / ค่าa2:

ด้วยอาร์เรย์[key,value]ประเภทอาร์เรย์มีสองวิธีที่จะไป

ขั้นแรกHash::[]ยังคงใช้งานได้ (เช่นเดียวกับที่ทำกับ*a1):

Hash[a2] # => {"apple"=>1, "banana"=>2}

จากนั้นก็ใช้#to_hงานได้ในขณะนี้:

a2.to_h  # => {"apple"=>1, "banana"=>2}

ดังนั้นคำตอบง่ายๆสองคำสำหรับกรณีอาร์เรย์ที่ซ้อนกันอย่างง่าย

สิ่งนี้ยังคงเป็นจริงแม้จะมีอาร์เรย์ย่อยเป็นคีย์หรือค่าเช่นเดียวกับa3:

Hash[a3] # => {"apple"=>1, "banana"=>2, ["orange", "seedless"]=>3, "pear"=>[4, 5]} 
a3.to_h  # => {"apple"=>1, "banana"=>2, ["orange", "seedless"]=>3, "pear"=>[4, 5]}

แต่ทุเรียนมีหนามแหลม (โครงสร้างผิดปกติทำให้เกิดปัญหา):

หากเราได้รับข้อมูลอินพุตที่ไม่สมดุลเราจะพบปัญหากับ#to_h:

a4.to_h  # => ArgumentError: wrong array length at 3 (expected 2, was 1)

แต่Hash::[]ยังใช้งานได้เพียงตั้งค่าnilเป็นค่าสำหรับdurian(และองค์ประกอบอาร์เรย์อื่น ๆ ใน a4 ซึ่งเป็นเพียงอาร์เรย์ 1 ค่า):

Hash[a4] # => {"apple"=>1, "banana"=>2, ["orange", "seedless"]=>3, "durian"=>nil}

การทำให้แบน - ใช้ตัวแปรใหม่a5และa6

คำตอบอื่น ๆ ที่กล่าวถึงไม่flattenว่าจะมีหรือไม่มี1อาร์กิวเมนต์ดังนั้นเรามาสร้างตัวแปรใหม่:

a5 = a4.flatten
# => ["apple", 1, "banana", 2,  "orange", "seedless" , 3, "durian"] 
a6 = a4.flatten(1)
# => ["apple", 1, "banana", 2, ["orange", "seedless"], 3, "durian"] 

ฉันเลือกที่จะใช้เป็นฐานข้อมูลเนื่องจากปัญหาความสมดุลที่เรามีซึ่งแสดงให้เห็นถึงกับa4 a4.to_hฉันคิดว่าโทรflattenอาจเป็นแนวทางหนึ่งที่ใครบางคนอาจใช้เพื่อพยายามแก้ปัญหานั้นซึ่งอาจมีลักษณะดังต่อไปนี้

flattenโดยไม่มีข้อโต้แย้ง ( a5):

Hash[*a5]       # => {"apple"=>1, "banana"=>2, "orange"=>"seedless", 3=>"durian"}
# (This is the same as calling `Hash[*a4.flatten]`.)

ได้อย่างรวดเร็วไร้เดียงสา, ปรากฏการทำงาน - แต่มันทำให้เราออกเท้าผิดปกติกับส้มไร้เมล็ดจึงยังทำให้สำคัญและค่า3durian

และสิ่งนี้a1ก็ไม่ได้ผลเช่นเดียวกับ:

a5.to_h # => TypeError: wrong element type String at 0 (expected array)

ดังนั้นจึงa4.flattenไม่มีประโยชน์สำหรับเราเราแค่ต้องการใช้Hash[a4]

flatten(1)กรณีที่ ( a6):

แต่การแบนเพียงบางส่วนล่ะ? เป็นที่น่าสังเกตว่าการโทรHash::[]โดยใช้splatอาร์เรย์แบบแบนบางส่วน ( a6) ไม่เหมือนกับการโทรHash[a4]:

Hash[*a6] # => ArgumentError: odd number of arguments for Hash

อาร์เรย์ก่อนแบนยังคงซ้อนอยู่ (วิธีรับอื่นa6):

แต่ถ้านี่เป็นวิธีที่เราได้รับอาร์เรย์ตั้งแต่แรก? (นั่นคือเปรียบเทียบได้กับa1มันเป็นข้อมูลอินพุตของเรา - ในครั้งนี้ข้อมูลบางส่วนอาจเป็นอาร์เรย์หรือวัตถุอื่น ๆ ) เราเห็นว่าHash[*a6]มันใช้ไม่ได้ผล แต่ถ้าเรายังคงต้องการพฤติกรรมที่องค์ประกอบสุดท้าย (สำคัญ! ดูด้านล่าง) ทำหน้าที่เป็นคีย์สำหรับnilค่า?

ในสถานการณ์เช่นนี้ยังมีวิธีการทำเช่นนี้โดยใช้Enumerable#each_sliceเพื่อให้ตัวเรากลับไปที่คู่คีย์ / ค่าเป็นองค์ประกอบในอาร์เรย์ด้านนอก:

a7 = a6.each_slice(2).to_a
# => [["apple", 1], ["banana", 2], [["orange", "seedless"], 3], ["durian"]] 

โปรดทราบว่าสิ่งนี้จะทำให้เราได้อาร์เรย์ใหม่ที่ไม่ " เหมือนกัน " a4แต่มีค่าเหมือนกัน:

a4.equal?(a7) # => false
a4 == a7      # => true

ดังนั้นเราจึงสามารถใช้Hash::[]:

Hash[a7] # => {"apple"=>1, "banana"=>2, ["orange", "seedless"]=>3, "durian"=>nil}
# or Hash[a6.each_slice(2).to_a]

แต่มีปัญหา!

สิ่งสำคัญคือต้องสังเกตว่าeach_slice(2)วิธีแก้ปัญหาจะทำให้สิ่งต่างๆกลับมามีสุขภาพดีได้ก็ต่อเมื่อคีย์สุดท้ายคือคีย์ที่ไม่มีค่า หากเราเพิ่มคู่คีย์ / ค่าพิเศษในภายหลัง:

a4_plus = a4.dup # just to have a new-but-related variable name
a4_plus.push(['lychee', 4])
# => [["apple",                1],
#     ["banana",               2],
#     [["orange", "seedless"], 3], # multi-value key
#     ["durian"],              # missing value
#     ["lychee", 4]]           # new well-formed item

a6_plus = a4_plus.flatten(1)
# => ["apple", 1, "banana", 2, ["orange", "seedless"], 3, "durian", "lychee", 4]

a7_plus = a6_plus.each_slice(2).to_a
# => [["apple",                1],
#     ["banana",               2],
#     [["orange", "seedless"], 3], # so far so good
#     ["durian",               "lychee"], # oops! key became value!
#     [4]]                     # and we still have a key without a value

a4_plus == a7_plus # => false, unlike a4 == a7

และสองแฮชที่เราได้รับจากสิ่งนี้มีความแตกต่างกันในลักษณะสำคัญ:

ap Hash[a4_plus] # prints:
{
                     "apple" => 1,
                    "banana" => 2,
    [ "orange", "seedless" ] => 3,
                    "durian" => nil, # correct
                    "lychee" => 4    # correct
}

ap Hash[a7_plus] # prints:
{
                     "apple" => 1,
                    "banana" => 2,
    [ "orange", "seedless" ] => 3,
                    "durian" => "lychee", # incorrect
                           4 => nil       # incorrect
}

(หมายเหตุ: ฉันใช้awesome_print'sap . เพียงเพื่อให้ง่ายต่อการแสดงโครงสร้างที่นี่ไม่มีความต้องการแนวคิดสำหรับการนี้)

ดังนั้นeach_sliceวิธีแก้ปัญหาสำหรับอินพุตแบบแบนที่ไม่สมดุลจะใช้งานได้ก็ต่อเมื่อบิตที่ไม่สมดุลอยู่ที่ส่วนท้ายสุด


ใช้สิ่งที่ได้:

  1. เมื่อเป็นไปได้ให้ตั้งค่าอินพุตให้กับสิ่งเหล่านี้เป็น[key, value]คู่ (อาร์เรย์ย่อยสำหรับแต่ละรายการในอาร์เรย์ภายนอก)
  2. เมื่อคุณสามารถทำได้จริง#to_hหรือHash::[]ทั้งสองอย่างก็ได้ผล
  3. หากคุณไม่สามารถที่จะHash::[]รวมกับเครื่องหมาย ( *) จะทำงานตราบใดที่ปัจจัยการผลิตที่มีความสมดุล
  4. ด้วยอาร์เรย์ที่ไม่สมดุลและแบนเป็นอินพุตวิธีเดียวที่จะใช้งานได้อย่างสมเหตุสมผลคือถ้ารายการสุดท้าย valueเป็นเพียงรายการเดียวที่ขาดหายไป

หมายเหตุด้านข้าง: ฉันโพสต์คำตอบนี้เพราะฉันรู้สึกว่ามีค่าที่จะเพิ่ม - คำตอบที่มีอยู่บางคำมีข้อมูลที่ไม่ถูกต้องและไม่มี (ที่ฉันอ่าน) ให้คำตอบที่สมบูรณ์เท่าที่ฉันพยายามทำที่นี่ ฉันหวังว่ามันจะเป็นประโยชน์ อย่างไรก็ตามฉันขอขอบคุณผู้ที่มาก่อนฉันซึ่งหลายคนให้แรงบันดาลใจสำหรับบางส่วนของคำตอบนี้


3

ต่อท้ายคำตอบ แต่ใช้อาร์เรย์ที่ไม่ระบุชื่อและการใส่คำอธิบายประกอบ:

Hash[*("a,b,c,d".split(',').zip([1,2,3,4]).flatten)]

แยกคำตอบโดยเริ่มจากภายใน:

  • "a,b,c,d" เป็นสตริงจริงๆ
  • split ในเครื่องหมายจุลภาคลงในอาร์เรย์
  • zip ที่ร่วมกับอาร์เรย์ต่อไปนี้
  • [1,2,3,4] คืออาร์เรย์จริง

ผลลัพธ์ระดับกลางคือ:

[[a,1],[b,2],[c,3],[d,4]]

แบนแล้วแปลงเป็น:

["a",1,"b",2,"c",3,"d",4]

แล้ว:

*["a",1,"b",2,"c",3,"d",4] คลายสิ่งนั้นลงใน "a",1,"b",2,"c",3,"d",4

ซึ่งเราสามารถใช้เป็นอาร์กิวเมนต์ของHash[]วิธีการ:

Hash[*("a,b,c,d".split(',').zip([1,2,3,4]).flatten)]

ซึ่งให้ผลตอบแทน:

{"a"=>1, "b"=>2, "c"=>3, "d"=>4}

นอกจากนี้ยังทำงานได้โดยไม่ต้องเครื่องหมาย ( *) และแผ่: =>Hash[("a,b,c,d".split(',').zip([1,2,3,4]))] {"a"=>1, "b"=>2, "c"=>3, "d"=>4}รายละเอียดเพิ่มเติมในคำตอบที่ฉันเพิ่ม
ลินเดส

0

ถ้าคุณมีอาร์เรย์ที่มีลักษณะเช่นนี้ -

data = [["foo",1,2,3,4],["bar",1,2],["foobar",1,"*",3,5,:foo]]

และคุณต้องการให้องค์ประกอบแรกของแต่ละอาร์เรย์กลายเป็นกุญแจสำหรับแฮชและองค์ประกอบที่เหลือกลายเป็นอาร์เรย์ค่าจากนั้นคุณสามารถทำสิ่งนี้ได้ -

data_hash = Hash[data.map { |key| [key.shift, key] }]

#=>{"foo"=>[1, 2, 3, 4], "bar"=>[1, 2], "foobar"=>[1, "*", 3, 5, :foo]}

0

ไม่แน่ใจว่าเป็นวิธีที่ดีที่สุดหรือไม่ แต่ได้ผล:

a = ["apple", 1, "banana", 2]
m1 = {}
for x in (a.length / 2).times
  m1[a[x*2]] = a[x*2 + 1]
end

b = [["apple", 1], ["banana", 2]]
m2 = {}
for x,y in b
  m2[x] = y
end

-1

หากค่าตัวเลขเป็นดัชนี seq เราอาจมีวิธีที่ง่ายกว่านี้ ... นี่คือการส่งรหัสของฉัน My Ruby ค่อนข้างเป็นสนิม

   input = ["cat", 1, "dog", 2, "wombat", 3]
   hash = Hash.new
   input.each_with_index {|item, index|
     if (index%2 == 0) hash[item] = input[index+1]
   }
   hash   #=> {"cat"=>1, "wombat"=>3, "dog"=>2}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.