Programing

루비 해시 배열

lottogame 2020. 5. 17. 10:28
반응형

루비 해시 배열


좋아, 여기에 거래가 있습니다. 나는 이것에 대한 해결책을 찾기 위해 여러 해 동안 인터넷 검색을 해왔으며 거기에 많은 사람들이 있지만 그들은 내가 찾고있는 일을하지 않는 것 같습니다.

기본적으로 나는 이런 식으로 배열 된 배열을 가지고 있습니다.

["item 1", "item 2", "item 3", "item 4"] 

이것을 해시로 변환하고 싶습니다.

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

즉, '짝수'인덱스에있는 항목은 키이고 'odd'인덱스에있는 항목은 값입니다.

이것을 깨끗하게하는 방법에 대한 아이디어가 있습니까? 무차별 강제 방법은 모든 짝수 색인을 별도의 배열로 가져온 다음 주위를 반복하여 값을 추가하는 것입니다.


a = ["item 1", "item 2", "item 3", "item 4"]
h = Hash[*a] # => { "item 1" => "item 2", "item 3" => "item 4" }

그게 다야. 이것을 splat 연산자 *라고합니다 .

@Mike Lewis 당 한 가지주의 사항 (의견에서) : "조심해야합니다. 루비는 스택에서 표시를 확장합니다. 대규모 데이터 세트로이 작업을 수행하는 경우 스택을 제거 할 것으로 예상됩니다."

따라서 대부분의 일반적인 사용 사례에서이 방법은 훌륭하지만 많은 데이터를 변환하려면 다른 방법을 사용하십시오. 예를 들어, @ Łukasz Niemier (또한 주석에서)는 큰 데이터 세트에이 방법을 제공합니다.

h = Hash[a.each_slice(2).to_a]

Ruby 2.1.0은 to_h원래 배열이 키-값 쌍의 배열로 구성된 경우 필요한 것을 수행 하는 메소드를 Array에 도입했습니다 . http://www.ruby-doc.org/core-2.1.0/Array.html#method -i-to_h .

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

Hash.[]배열의 값과 함께 사용 하십시오. 예를 들면 다음과 같습니다.

arr = [1,2,3,4]
Hash[*arr] #=> gives {1 => 2, 3 => 4}

또는 배열 배열이있는 경우 다음을 [key, value]수행 할 수 있습니다.

[[1, 2], [3, 4]].inject({}) do |r, s|
  r.merge!({s[0] => s[1]})
end # => { 1 => 2, 3 => 4 }

이것은 내가 인터넷 검색 할 때 찾고 있던 것입니다.

[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v } => {:a=>1, :b=>2}


Enumerator포함 Enumerable합니다. 이후 2.1, Enumerable같은 방법이있다 #to_h. 그래서 우리는 다음과 같이 쓸 수 있습니다.

a = ["item 1", "item 2", "item 3", "item 4"]
a.each_slice(2).to_h
# => {"item 1"=>"item 2", "item 3"=>"item 4"}

#each_slice블록이 없으면 Enumerator위의 설명 #to_h에 따라 Enumerator객체를 제공 할 수 있기 때문에 객체 에서 메소드를 호출 할 수 있습니다 .


단일 배열의 경우 이와 같이 시도 할 수 있습니다

irb(main):019:0> a = ["item 1", "item 2", "item 3", "item 4"]
  => ["item 1", "item 2", "item 3", "item 4"]
irb(main):020:0> Hash[*a]
  => {"item 1"=>"item 2", "item 3"=>"item 4"}

배열의 배열

irb(main):022:0> a = [[1, 2], [3, 4]]
  => [[1, 2], [3, 4]]
irb(main):023:0> Hash[*a.flatten]
  => {1=>2, 3=>4}

a = ["item 1", "item 2", "item 3", "item 4"]
Hash[ a.each_slice( 2 ).map { |e| e } ]

또는 당신이 싫어하는 경우 Hash[ ... ]:

a.each_slice( 2 ).each_with_object Hash.new do |(k, v), h| h[k] = v end

또는 기능 프로그래밍이 깨진 게으른 팬인 경우 :

h = a.lazy.each_slice( 2 ).tap { |a|
  break Hash.new { |h, k| h[k] = a.find { |e, _| e == k }[1] }
}
#=> {}
h["item 1"] #=> "item 2"
h["item 3"] #=> "item 4"

모든 답변은 시작 배열이 고유하다고 가정합니다. OP는 중복 항목이있는 배열을 처리하는 방법을 지정하지 않아 중복 키가 발생했습니다.

봅시다 :

a = ["item 1", "item 2", "item 3", "item 4", "item 1", "item 5"]

item 1 => item 2bij가 재정의 되면 쌍을 잃게됩니다 item 1 => item 5.

Hash[*a]
=> {"item 1"=>"item 5", "item 3"=>"item 4"}

reduce(&:merge!)동일한 제거 결과를 포함한 모든 방법 .

It could be that this is exactly what you expect, though. But in other cases, you probably want to get a result with an Array for value instead:

{"item 1"=>["item 2", "item 5"], "item 3"=>["item 4"]}

The naïve way would be to create a helper variable, a hash that has a default value, and then fill that in a loop:

result = Hash.new {|hash, k| hash[k] = [] } # Hash.new with block defines unique defaults.
a.each_slice(2) {|k,v| result[k] << v }
a
=> {"item 1"=>["item 2", "item 5"], "item 3"=>["item 4"]}

It might be possible to use assoc and reduce to do above in one line, but that becomes much harder to reason about and read.

참고URL : https://stackoverflow.com/questions/4028329/array-to-hash-ruby

반응형