[ruby] 해시 값을 변경하는 방법은 무엇입니까?

나는 각을 교체하고 싶습니다 value과 함께 해시 value.some_method.

예를 들어 간단한 해시가 주어진 경우 :

{"a" => "b", "c" => "d"}` 

모든 값은 .upcased 여야 하므로 다음과 같습니다.

{"a" => "B", "c" => "D"}

나는 시도 #collect하고 #map있지만, 항상 그냥 배열을 얻는다. 이를 수행하는 우아한 방법이 있습니까?

최신 정보

젠장, 잊어 버렸습니다. 해시가 변경되어서는 안되는 인스턴스 변수에 있습니다. 변경된 값이있는 새 해시가 필요하지만 해당 변수를 명시 적으로 정의한 다음이를 채우는 해시를 반복하는 것을 선호하지 않습니다. 다음과 같은 것 :

new_hash = hash.magic{ ... }



답변

my_hash.each { |k, v| my_hash[k] = v.upcase } 

또는 비파괴 적으로 수행하고 싶은 경우 수정하는 대신 새 해시를 반환합니다 my_hash.

a_new_hash = my_hash.inject({}) { |h, (k, v)| h[k] = v.upcase; h } 

이 마지막 버전에는 키도 변환 할 수있는 추가 이점이 있습니다.


답변

ruby 2.4.0네이티브 Hash#transform_values메서드를 사용할 수 있기 때문에 :

hash = {"a" => "b", "c" => "d"}
new_hash = hash.transform_values(&:upcase)
# => {"a" => "B", "c" => "D"}

파괴적인 Hash#transform_values!버전도 있습니다.


답변

값을 수집하고이를 Array에서 Hash로 다시 변환 할 수 있습니다.

이렇게 :

config = Hash[ config.collect {|k,v| [k, v.upcase] } ]


답변

이렇게하면됩니다.

my_hash.each_with_object({}) { |(key, value), hash| hash[key] = value.upcase }

inject장점과는 반대로 블록 내에서 해시를 다시 반환 할 필요가 없다는 것입니다.


답변

이 기능을 시도하십시오 :

h = {"a" => "b", "c" => "d"}
h.each{|i,j| j.upcase!} # now contains {"a" => "B", "c" => "D"}.


답변

ActiveSupport v4.2.0 에는 방법이 있습니다 . 호출 transform_values되고 기본적으로 각 키-값 쌍에 대해 블록을 실행합니다.

그들은 그것을 사용하고 있기 때문에 each반복하는 것보다 더 좋은 방법은 없다고 생각합니다.

hash = {sample: 'gach'}

result = {}
hash.each do |key, value|
  result[key] = do_stuff(value)
end

최신 정보:

Ruby 2.4.0부터 기본적으로 #transform_values#transform_values!.


답변

한 단계 더 나아가 중첩 된 해시에서이 작업을 수행 할 수 있습니다. 확실히 이것은 Rails 프로젝트에서 상당한 양의 일이 발생합니다.

다음은 params 해시가 UTF-8인지 확인하는 몇 가지 코드입니다.

  def convert_hash hash
    hash.inject({}) do |h,(k,v)|
      if v.kind_of? String
        h[k] = to_utf8(v)
      else
        h[k] = convert_hash(v)
      end
      h
    end
  end

  # Iconv UTF-8 helper
  # Converts strings into valid UTF-8
  #
  # @param [String] untrusted_string the string to convert to UTF-8
  # @return [String] your string in UTF-8
  def to_utf8 untrusted_string=""
    ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
    ic.iconv(untrusted_string + ' ')[0..-2]
  end