Извлечение конкретного значения из многомерного хэша в Ruby по ключевым имени

StackOverflow https://stackoverflow.com/questions/2238849

  •  19-09-2019
  •  | 
  •  

Вопрос

Допустим, у меня есть многомерный хэш, и в одном из субхаша у меня есть пара значений Key =>, которую мне нужно получить на ключе. как мне это сделать?

Пример хэши:

h={:x=>1,:y=>2,:z=>{:a=>{:k=>"needle"}}}
h={:k=>"needle"}

Ключ всегда: k, и мне нужно получить "иглу"

Я заметил, что не существует «сглаженной» функции для хэшей в Ruby 1.8, но если бы это было там, я думаю, я просто сделаю

h.flatten[:k]

Я полагаю, мне нужно написать для этого рекурсивную функцию?

Благодарность

Это было полезно?

Решение

Вы всегда можете написать свое собственное расширение, специфичное для миссии в хэш, который делает грязную работу для вас:

class Hash
  def recursive_find_by_key(key)
    # Create a stack of hashes to search through for the needle which
    # is initially this hash
    stack = [ self ]

    # So long as there are more haystacks to search...
    while (to_search = stack.pop)
      # ...keep searching for this particular key...
      to_search.each do |k, v|
        # ...and return the corresponding value if it is found.
        return v if (k == key)

        # If this value can be recursively searched...
        if (v.respond_to?(:recursive_find_by_key))
          # ...push that on to the list of places to search.
          stack << v
        end
      end
    end
  end
end

Вы можете использовать это довольно просто:

h={:x=>1,:y=>2,:z=>{:a=>{:k=>"needle"}}}

puts h.recursive_find_by_key(:k).inspect
# => "needle"

h={:k=>"needle"}

puts h.recursive_find_by_key(:k).inspect
# => "needle"

puts h.recursive_find_by_key(:foo).inspect
# => nil

Другие советы

Если вам нужно просто принести значение ключа, но не знаете, насколько глубоко это ключ, используйте этот фрагмент

def find_tag_val(hash, tag)
  hash.map do |k, v|
    return v if k.to_sym == tag
    vr = find_tag_val(v, tag) if v.kind_of?(Hash)
    return vr if vr
  end
  nil #othervice
end 

h = {message: { key: 'val'}}
find_tag_val(h, :key) #=> 'val'
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top