【问题标题】:How collect values of a specified key recursively in a Array/Hash如何在数组/哈希中递归地收集指定键的值
【发布时间】:2016-05-21 04:19:24
【问题描述】:

我有以下数组(没有深度限制):

 [
   {
     name: "foo",
     age: 12,
     children: [{
         name: "zoo",
         age: 44
       },
       {
         name: "taz",
         age: 17,
         children: [{
             name: 'tof',
             age: 23
           },
           {
             name: 'tok',
             age: 42
           }
         ]
       }
     ]
   },
   {
     name: "bar",
     age: 54
   }
 ]

我想收集键 name 的所有不同值,在此示例中,结果将是:

(顺序无所谓)

['foo', 'zoo', 'taz', 'tof', 'tok', 'bar']

具有类似的功能

def func(my_array, "name")

你知道我应该如何编写这个函数吗?

【问题讨论】:

  • 你只是想收集所有的叶节点字符串吗?
  • 不,所有不同的值都带有键“name”
  • 您提供的数组无效

标签: arrays ruby function recursion hash


【解决方案1】:

假设您知道子结构在:children 下:

def extract(sequence, key)
  sequence.flat_map do |hash|
    [hash[key], *extract(hash[:children] || [], key)]
  end
end

【讨论】:

  • 鉴于问题的陈述,在我看来,您的假设没有合理的替代方案。
  • @CarySwoveland,可能是 OP 想要迭代所有可迭代的值。
【解决方案2】:

这是一种使用case 区分您将遇到的各种对象类型的方法:

def find_names(object, key_name)
  case (object)
  when Array
    object.flat_map do |e|
      find_names(e, key_name)
    end
  when Hash
    [ object[key_name] ] + find_names(object.values, key_name).compact
  end
end

【讨论】:

  • 为什么括号中有object?这只是给我的,可能有什么东西可以放在()
  • 不需要使用括号。我只是把它们放在那里以获得最大的清晰度。
  • 这个例子没有,但是很容易适应。
【解决方案3】:

这是一种快速但脆弱的正则表达式方法

def find_nested(arr, key)
  arr.to_s.scan(/#{key.to_sym}=>"([^"]+)/).flatten
end

【讨论】:

    【解决方案4】:
    def find_em(arr)
      arr.each_with_object([]) do |h,a|
        a << h[:name]
        a.concat(find_em(h[:children])) if h.key?(:children)
      end
    end
    
    find_em(arr)
      #=> ["foo", "zoo", "taz", "tof", "tok", "bar"] 
    

    【讨论】:

    • 第一次工作!
    猜你喜欢
    • 2016-07-11
    • 2018-11-03
    • 2017-09-27
    • 1970-01-01
    • 2016-09-23
    • 2014-05-30
    • 1970-01-01
    • 1970-01-01
    • 2013-03-22
    相关资源
    最近更新 更多