ฉันจะรวมสองแฮชโดยไม่เขียนทับคีย์ซ้ำในรูบีได้อย่างไร


141

มีวิธีที่ง่ายหรือสง่าในการรวมสองแฮชโดยไม่ต้องเขียนทับคีย์ซ้ำหรือไม่?

นั่นคือถ้ากุญแจมีอยู่ในแฮชดั้งเดิมฉันไม่ต้องการเปลี่ยนค่าของมัน


คุณหมายถึงอาร์เรย์ (เช่น: '' a ',' b ',' c ']) หรือแฮช (เช่น: {' a '=> 1,' b '=> 2,' c '=> 3}) ?
Alex Reisner

ขออภัยผมได้พูดคุยเกี่ยวกับแฮช :)
เคลาดิโอ Acciaresi

คำตอบ:


233

หากคุณมีแฮชสองครั้งoptionsและdefaultsและคุณต้องการรวมdefaultsเข้าด้วยกันoptionsโดยไม่ต้องเขียนทับคีย์ที่มีอยู่สิ่งที่คุณต้องการทำจริงๆคือการย้อนกลับ: รวมoptionsเข้ากับdefaults:

options = defaults.merge(options)

หรือถ้าคุณใช้ Rails คุณสามารถทำได้:

options.reverse_merge!(defaults)

เห็นด้วยอย่างยิ่งขอบคุณมากสำหรับ reverse_merge! วิธีการไม่ได้รู้ว่ามัน :)
เคลาดิโอ Acciaresi

ทำไมต้องใช้วงเล็บที่นี่ คุณไม่สามารถทำ default.merge ตัวเลือกที่ปรากฏ
Donato

1
พวกเขากำลังreverse_merge!ลดค่าลงเนื่องจากปัญหาด้านความปลอดภัยในราง 5.1
Mirv - Matt

1
@ Mirv-Matt - ฉันไม่เห็นข้อความแจ้งค่าเสื่อมราคา apidock.com/rails/v6.0.0/Hash/reverse_merge%21
Kshitij

17

มีวิธีหนึ่งในไลบรารี Ruby มาตรฐานที่จะรวมแฮชโดยไม่เขียนทับค่าที่มีอยู่หรือกำหนดแฮชใหม่

important_hash.merge!(defaults) { |key, important, default| important }

3

หากปัญหาของคุณคือการแฮชดั้งเดิมและคีย์ที่สองทั้งคู่อาจมีคีย์ที่ซ้ำกันและคุณไม่ต้องการเขียนทับในทิศทางใดทิศทางหนึ่งคุณอาจต้องไปรวมด้วยตนเองอย่างง่ายพร้อมการตรวจสอบการชนและการจัดการบางอย่าง:

hash2.each_key do |key|
  if ( hash1.has_key?(key) )
       hash1[ "hash2-originated-#{key}" ] = hash2[key]
  else
       hash1[key]=hash2[key]
  end
end

เห็นได้ชัดว่านี่เป็นพื้นฐานมากและถือว่า hash1 ไม่มีคีย์ใด ๆ ที่เรียกว่า "hash2 ที่มาจากอะไรก็ตาม" - คุณอาจจะดีกว่าแค่เพิ่มตัวเลขลงในคีย์ดังนั้นมันจึงกลายเป็น key1, key2 และอื่น ๆ จนกว่าคุณจะกด อันที่ไม่ได้อยู่ใน hash1 นอกจากนี้ฉันยังไม่ได้ทับทิมใด ๆ มาสองสามเดือนดังนั้นนั่นอาจไม่ถูกต้องทางไวยากรณ์ แต่คุณควรจะได้รับส่วนสำคัญ

หรือกำหนดค่าของคีย์เป็นอาร์เรย์อีกครั้งเพื่อให้ hash1 [key] ส่งคืนค่าดั้งเดิมจาก hash1 และค่าจาก hash2 ขึ้นอยู่กับสิ่งที่คุณต้องการให้ผลลัพธ์ของคุณเป็นจริง


ถ้าไม่เก็บคีย์ทั้งสองไว้ แต่จะเพิ่มค่าของคีย์เดียวกันล่ะ
Tom KC Chiu

1
@ TomK.C.Chiu นั่นจะขึ้นอยู่กับสถานการณ์ที่เราไม่สามารถตัดสินได้จากคำถาม - ถ้าค่าใน hash1 เป็นสตริงและ hash2 เป็นจำนวนเต็ม? สำหรับบางกรณีที่อาจเป็นตัวเลือกที่ทำงานได้ แต่บ่อยครั้งมันจะทำให้เกิดปัญหา - ข้อเสนอแนะของการใช้รายการสำหรับค่าทำงานรอบนี้ค่อนข้างเรียบร้อย
ลนนาตรอน

0

ที่นี่คุณสามารถรวม 2 แฮชของคุณโดย reverse_merge

order = {
 id: 33987,
 platform: 'web'
}

user = {
  name: 'Jhon Doe',
  email: 'jhon.doe@gmail.com' 
}
newHash = oder.reverse_merge!(user)
render json: { data: newHash, status: 200 }

0

หากคุณต้องการรวมสองแฮชoptionsและdefaultsโดยไม่ต้องเขียนทับแฮชปลายทางคุณอาจตรวจสอบselectว่ามีคีย์อยู่ในแฮชปลายทางแล้วหรือไม่ นี่คือโซลูชัน Ruby บริสุทธิ์ที่ไม่มี Rails:

options  = { "a" => 100, "b" => 200 }
defaults = { "b" => 254, "c" => 300 }
options.merge!(defaults.select{ |k,_| not options.has_key? k })

# output
# => {"a"=>100, "b"=>200, "c"=>300}

หรือถ้ามีคีย์ แต่มีnilและคุณต้องการเขียนทับมัน:

options.merge!(defaults.select{ |k,_| options[k].nil? })
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.