Program Tip

해시 할 해시 배열

programtip 2020. 11. 29. 12:11
반응형

해시 할 해시 배열


예를 들어, 단일 해시 배열이 있습니다.

a = [{a: :b}, {c: :d}]

이것을 이것으로 변환하는 가장 좋은 방법은 무엇입니까?

{a: :b, c: :d}

당신은 사용할 수 있습니다

a.reduce Hash.new, :merge

직접 산출하는

{:a=>:b, :c=>:d}

충돌의 경우 순서가 중요합니다. 후기 해시는 이전 매핑을 재정의합니다. 예를 들면 다음과 같습니다.

[{a: :b}, {c: :d}, {e: :f, a: :g}].reduce Hash.new, :merge   # {:a=>:g, :c=>:d, :e=>:f}

다음을 사용할 수 있습니다 .inject.

a.inject(:merge)
#=> {:a=>:b, :c=>:d}

데모

병합 된 두 개의 반복에서 각 반복에 대해 새 해시를 시작합니다. 이를 방지하기 위해 파괴적 :merge!(또는 :update, 동일)을 사용할 수 있습니다 .

a.inject(:merge!)
#=> {:a=>:b, :c=>:d}

데모


이 두 가지 :

total_hash = hs.reduce({}) { |acc_hash, hash| acc_hash.merge(hash) }
total_hash = hs.reduce({}, :merge)

Hash#merge각 반복마다 새 해시 생성하므로 큰 해시를 빌드하는 경우 문제가 될 수 있습니다. 이 경우 update대신 사용하십시오.

total_hash = hs.reduce({}, :update)

다른 방법은 해시를 쌍으로 변환 한 다음 최종 해시를 만드는 것입니다.

total_hash = hs.flat_map(&:to_a).to_h

이 답변을 보았고 성능 측면에서 두 옵션을 비교하여 어느 것이 더 나은지 확인하고 싶었습니다.

  1. a.reduce Hash.new, :merge
  2. a.inject(:merge)

루비 벤치 마크 모듈을 사용하면 옵션 (2) a.inject(:merge)가 더 빠릅니다.

비교에 사용되는 코드 :

require 'benchmark'

input = [{b: "c"}, {e: "f"}, {h: "i"}, {k: "l"}]
n = 50_000

Benchmark.bm do |benchmark|
  benchmark.report("reduce") do
    n.times do
      input.reduce Hash.new, :merge
    end
  end

  benchmark.report("inject") do
    n.times do
      input.inject(:merge)
    end
  end
end

결과는

       user     system      total        real
reduce  0.125098   0.003690   0.128788 (  0.129617)
inject  0.078262   0.001439   0.079701 (  0.080383)

이 시도

a.inject({}){|acc, hash| acc.merge(hash)} #=> {:a=>:b, :c=>:d}

그냥 사용

a.reduce(:merge)
#=> {:a=>:b, :c=>:d}

배열로 변환 [[:a, :b]]한 후 모든 것을 해시로 변환 할 수 있습니다.{:a=>:b}

# it works like [[:a, :b]].to_h => {:a=>:b}

[{a: :b}, {c: :d}].map { |hash| hash.to_a.flatten }.to_h

# => {:a=>:b, :c=>:d}

참고 URL : https://stackoverflow.com/questions/10943909/array-of-hashes-to-hash

반응형