将哈希值和符号数组转换为唯一值

时间:2017-09-14 12:26:01

标签: ruby

我有这个数组[{:foo=>[{:bar=>[:baz]}]}, :foo, {:foo=>[{:bar=>[:bat]}]}, :bar] 如你所见,有符号和哈希。我想要做的是避免重复每个键或键内部值。 我想要的输出是:

[{:foo=>[{:bar=>[:baz, :bat]}]}, :bar]

正如你所看到的,没有重复foo或重复foo => bar。

我在这个问题上被困了好几个小时,我无法实现。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

以下会以某种方式运作:

input = [{:foo=>[{:bar=>[:baz]}]},
         :foo,
         {:foo=>[{:bar=>[:bat]}]},
         :bar]

builder = ->(value, acc = {}) {
  case value
  when Hash
    value.each_with_object(acc) do |(k, v), acc|
      builder.(v, acc[k] ||= {})
    end
  when Array
    value.each_with_object(acc) do |v, acc|
      builder.(v, acc)
    end
  else acc[value] ||= {}
  end
}

上面已经产生了或多或少可接受的结果:

puts (built = builder.(input)).inspect
#⇒ {:foo=>{:bar=>{:baz=>{}, :bat=>{}}}, :bar=>{}}

要准确地返回你想要的链接lambda(你无法事先告诉对象是否是一个叶子):

fixer = ->(acc) {
  result = acc.all? { |*v| v.last.empty? } ? acc.keys : 
    acc.map { |k, v| v.empty? ? k : { k => fixer.(v) } }
  result.size == 1 ? result.first : result
}

puts fixer.(built).inspect
#⇒ [{:foo=>{:bar=>[:baz, :bat]}}, :bar]

我相信您可以使用此代码来管理它以更好地满足您的需求。