#ruby #hash
#массивы #ruby #хэш #splat
Вопрос:
У меня есть вложенный хэш данных
foo => {
'user' => {
'address' => {
'street' => '1234'
}
}
}
Я могу получить доступ к значениям, используя Hash.dig
foo.dig('user', 'address', 'street')
1234
Как бы вы использовали hash.dig, когда значения являются переменными и определены в массиве?
query=["users", "address", "street"]
foo.dig(query) # <= doesn't work
foo.dig(query.to_s) # <= doesn't work
Глядя на документы ruby, Hash.dig, похоже, принимает несколько параметров, но не принимает массив
https://ruby-doc.org/core-2.3.0_preview1/Hash.html#method-i-dig
Комментарии:
1. Имейте в виду, что массив является допустимым хэш-ключом, поэтому вызов
Hash#dig
с аргументом массива является допустимым и разумным.
Ответ №1:
Вы можете сделать это с помощью оператора splat, чтобы разделить массив на список аргументов таким образом:
foo.dig(*query)
Комментарии:
1. Кстати, имя — «оператор splat»
Ответ №2:
Я бы использовал ответ Алекса для типичного варианта использования, но поскольку он разбивает массив на аргументы, накладных расходов больше, и при больших входных данных я получаю ошибку stack too deep. Это не ошибка, с которой вы столкнетесь, если у вас нет огромного списка, но, возможно, стоит понять в любом случае.
# one million keys
# note that none of these are actually present in the hash
query = 1.upto(1_000_000).to_a
foo.dig(*query)
# => StackTooDeep
query.reduce(foo) do |memo, key|
memoamp;.dig(key) || break
end
# => returns nil instantly
Комментарии:
1. Если у вас структура глубиной в миллион уровней, у вас, вероятно, есть другие проблемы.
2. Да, согласен, но я думаю, что урок здесь не столько о dig, сколько о том, что разделение массивов на аргументы не работает с большими массивами.
3. @maxpleaner Спасибо за ответ! Это заставило меня задуматься о других вариантах использования
reduce
paradigm, помимо использования, обсуждаемого в этом посте (для обхода «splat» для больших массивов). И нет, я не воспринял этот игрушечный пример как совет по созданию монстров глубиной в миллион уровней. Наоборот! Я просто подозреваю, что в один прекрасный день мне, возможно, придется отлаживать код, в котором кто-то случайно создал такую вещь. Может быть, даже несколько вещей, если бы они знали о циклах. 🙂4. Хах, приятно слышать. Да, я чувствую, что улучшение перечислимых методов стало первым способом улучшения моего кода за последние несколько лет.