鉴于以下数据结构:
[
[:created_at, "07/28/2017"],
[:valid_record, "true"],
[:cs_details, { gender: 'm', race: 'w', language: nil } ],
[:co_details, { description: 'possess', extra: { a: 'a', b: 'b', c: 'c'} } ]
]
我想要一组键/值对数组:
[
[:created_at, "07/28/2017"],
[:valid_record, "true"],
[:gender, 'm'],
[:race, 'w'],
[:description, "process"]
[:a, "a"],
[:b, "b"],
[:c, "c"]
]
问题是我不知道如何压扁这些哈希。 flatten
没有做任何事情:
arr.map(&:flatten)
=> [[:created_at, "07/28/2017"], [:valid_record, "true"], [:cs_details, {:gender=>"m", :race=>"w", :language=>nil}], [:co_details, {:description=>"possess", :extra=>{:a=>"a", :b=>"b", :c=>"c"}}]]
所以我知道flat_map
也无济于事。我甚至无法使用to_a
将这些哈希值转换为数组:
arr.map(&:to_a)
=> [[:created_at, "07/28/2017"], [:valid_record, "true"], [:cs_details, {:gender=>"m", :race=>"w", :language=>nil}], [:co_details, {:description=>"possess", :extra=>{:a=>"a", :b=>"b", :c=>"c"}}]]
上述方法的问题在于它们只能处理顶级索引。这些哈希嵌套在数组中。所以我尝试reduce然后在result:
上调用flat_maparr.reduce([]) do |acc, (k,v)|
if v.is_a?(Hash)
acc << v.map(&:to_a)
else
acc << [k,v]
end
acc
end.flat_map(&:to_a)
=> [:created_at, "07/28/2017", :valid_record, "true", [:gender, "m"], [:race, "w"], [:language, nil], [:description, "possess"], [:extra, {:a=>"a", :b=>"b", :c=>"c"}]]
不太相似,但更接近。有什么建议吗?
答案 0 :(得分:2)
▶ flattener = ->(k, v) do
▷ case v
▷ when Enumerable then v.flat_map(&flattener)
▷ when NilClass then []
▷ else [k, v]
▷ end
▷ end
#⇒ #<Proc:0x000000032169e0@(pry):26 (lambda)>
▶ input.flat_map(&flattener).each_slice(2).to_a
#⇒ [
# [:created_at, "07/28/2017"],
# [:valid_record, "true"],
# [:gender, "m"],
# [:race, "w"],
# [:description, "possess"],
# [:a, "a"],
# [:b, "b"],
# [:c, "c"]
# ]
答案 1 :(得分:1)
我认为你会从编写一个将在数组中的每个项目上调用的辅助函数中受益。为了使结果一致,我们将确保此函数始终返回一个数组数组。换句话说,一个包含一个或多个&#34;条目的数组,&#34;取决于索引1处的东西是否为散列。
def extract_entries((k,v))
if v.is_a? Hash
v.to_a
else
[[k, v]]
end
end
尝试一下:
require 'pp'
pp data.map {|item| extract_entries(item)}
输出:
[[[:created_at, "07/28/2017"]],
[[:valid_record, "true"]],
[[:gender, "m"], [:race, "w"], [:language, nil]],
[[:description, "possess"], [:extra, {:a=>"a", :b=>"b", :c=>"c"}]]]
现在,我们可以按一个级别展平,以达到您想要的格式:
pp data.map {|item| extract_entries(item)}.flatten(1)
输出:
[[:created_at, "07/28/2017"],
[:valid_record, "true"],
[:gender, "m"],
[:race, "w"],
[:language, nil],
[:description, "possess"],
[:extra, {:a=>"a", :b=>"b", :c=>"c"}]]
答案 2 :(得分:0)
def to_flat(arr)
arr.flat_map { |k,v| v.is_a?(Hash) ? to_flat(v.compact) : [[k, v]] }
end
测试
arr = [ [:created_at, "07/28/2017"],
[:valid_record, "true"],
[:cs_details, { gender: 'm', race: 'w', language: nil } ],
[:co_details, { description: 'possess', extra: { a: 'a', b: 'b', c: 'c'} } ] ]
to_flat(arr)
#=> [[:created_at, "07/28/2017"], [:valid_record, "true"], [:gender, "m"],
# [:race, "w"], [:description, "possess"], [:a, "a"], [:b, "b"], [:c, "c"]]