Ruby хэш-значение доступа из массива строк

У меня есть хеш, как показано ниже:

hash = {"a": [{"c": "d", "e": "f"}] }

Обычно мы можем получить к нему доступ, как hash["a"][0]["c"],

Но у меня есть строка вроде:

string = "a[0]['c']"

(Это может измениться в зависимости от ввода пользователя)

Есть ли простой способ получить доступ к хешу, используя приведенные выше строковые значения?

3 ответа

Решение

Предполагая, что пользователь вводит числа для индексов массива и слова для ключей хеша:

keys = string.scan(/(\d+)|(\w+)/).map do |number, string|
  number&.to_i || string.to_sym
end

hash.dig(*keys) # => "d"

Вы могли бы сделать это:

hash = { 'a' => [{ 'c' => 'd', 'e' => 'f' }] }

string = "a[0]['c']"

def nested_access(object, string)
  string.scan(/\w+/).inject(object) do |hash_or_array, i|
    case hash_or_array
    when Array then hash_or_array[i.to_i]
    when Hash then hash_or_array[i] || hash_or_array[i.to_sym]
    end
  end
end

puts nested_access(hash, string) # => "d"

Входная строка сканируется на наличие букв, подчеркиваний и цифр. Все остальное игнорируется:

puts nested_access(hash, "a/0/c") #=> "d"
puts nested_access(hash, "a 0 c") #=> "d"
puts nested_access(hash, "a;0;c") #=> "d"

Неверное значение доступа вернет ноль.

Он также работает с символом в качестве ключей:

hash = {a: [{c: "d", e: "f"}]}
puts nested_access(hash, "['a'][0]['c']")

Это дает преимущество, заключающееся в том, что он не слишком строг в отношении пользовательского ввода, но у него есть недостаток - не распознавать ключи с пробелами.

Ты можешь использовать gsub очистить другие символы в массиве и использовать этот массив для доступа к вашему хешу

hash = {"a": [{"c": "d", "e": "f"}] }

string = "a[0]['c']"

tmp = string.gsub(/[\[\]\']/, '').split('')
#=> ["a", "0", "c"]

hash[tmp[0].to_sym][tmp[1].to_i][tmp[2].to_sym]
#=> "d"
Другие вопросы по тегам