使用字符串数组来检查哈希

时间:2018-04-26 19:21:17

标签: ruby

考虑嵌套哈希中可能存在的属性数组:

property_selector = ['component_styles', 'styles', 'background' ,'color']

以下嵌套哈希值是可能的:

object_to_search_containing_property = {
    some_attr: 'blah',
    component_styles: {
        styles: {
            background: {
                color: 'fff'
            }
        }
    }
}

object_to_search_not_containing_property = {
    some_attr: 'blah',
    component_styles: {

    }
}

有没有办法迭代property_selector来搜索这些对象,检查属性嵌套的每个级别?

Ruby中有什么东西可以做类似的事情:

property_selector.each do |property|
    object[property][next_property] ... [property.length - 1]
end

更新

道歉之前没有提及,但我使用的是Ruby版本 2.2.3

3 个答案:

答案 0 :(得分:6)

您使用的是Ruby 2.3+吗?试试Hash#dig

object_to_search_containing_property.dig(*property_selector) # => "fff"
object_to_search_not_containing_property.dig(*property_selector) # => nil

唯一的问题是属性选择器数组的元素是字符串,但是您要使用符号键构建嵌套对象。像这样定义属性选择器数组,而不是让上面的代码工作:

property_selector = [:component_styles, :styles, :background, :color]

或者,如果您无法控制数组的定义方式,您可以动态转换它:

object.dig(*property_selector.map(&:to_sym))

这是一种便携式方法:

def dig(object, *keys)
  keys.each do |key|
    break unless object.respond_to?(:[])

    object = object[key]
  end

  object
end

dig(object_to_search_containing_property, *property_selector) # => "fff"
dig(object_to_search_not_containing_property, *property_selector) # => nil

关于属性选择器数组的相同警告也适用于此处。

答案 1 :(得分:0)

如果您正在寻找获得property_selector值的方法,那么hashie gem可能会有所帮助。它可以做很多事情,所以我鼓励大家查看一下。在这种情况下,可以使用DeepFind扩展名。以下是docs的示例:

require 'hashie'

user = {
  name: { first: 'Bob', last: 'Boberts' },
  groups: [
    { name: 'Rubyists' },
    { name: 'Open source enthusiasts' }
  ]
}

user.extend Hashie::Extensions::DeepFind

user.deep_find(:name)   #=> { first: 'Bob', last: 'Boberts' }
user.deep_detect(:name) #=> { first: 'Bob', last: 'Boberts' }

user.deep_find_all(:name) #=> [{ first: 'Bob', last: 'Boberts' }, 'Rubyists', 'Open source enthusiasts']
user.deep_select(:name)   #=> [{ first: 'Bob', last: 'Boberts' }, 'Rubyists', 'Open source enthusiasts']

它可以搜索散列中包含的具有指定键的对象的任何Enumerable。

基于.travis.yml gem支持mri >= 2.0.0jruby-9.0.5.0rbx-3

答案 2 :(得分:0)

我在这里写的是错的。如果时间允许,我会纠正它,但是现在,不要理会。