我有>>> df.groupby("Dept")["User"].nunique()
Dept
Cook 2
Home 1
Sports 1
Travel 1
Name: User, dtype: int64
>>> df.groupby("Dept")["User"].nunique().reset_index()
Dept User
0 Cook 2
1 Home 1
2 Sports 1
3 Travel 1
与许多其他OpenStruct
嵌套。将它们全部转换为JSON的最佳方法是什么?
理想情况下:
OpenStructs
现实
x = OpenStruct.new
x.y = OpenStruct.new
x.y.z = OpenStruct.new
z = 'hello'
x.to_json
// {y: z: 'hello'}
答案 0 :(得分:9)
没有默认方法可以完成此类任务,因为内置的#to_hash
会返回哈希表示,但它并没有深度转换值。
如果某个值为OpenStruct
,则会将其返回,并且不会转换为Hash
。
然而,解决这个问题并不复杂。您可以创建一个遍历OpenStruct
实例中每个键/值的方法(例如,使用each_pair
),如果值为OpenStruct
,则以递归方式下降到嵌套OpenStruct
中并返回Hash
只是Ruby基本类型。
然后可以使用Hash
或.to_json
轻松序列化此类JSON.dump(hash)
。
这是一个非常快速的例子
def openstruct_to_hash(object, hash = {})
object.each_pair do |key, value|
hash[key] = value.is_a?(OpenStruct) ? openstruct_to_hash(value) : value
end
hash
end
openstruct_to_hash(OpenStruct.new(foo: 1, bar: OpenStruct.new(baz: 2)))
# => {:foo=>1, :bar=>{:baz=>2}}
答案 1 :(得分:9)
修复上述解决方案以处理数组
def open_struct_to_hash(object, hash = {})
object.each_pair do |key, value|
hash[key] = case value
when OpenStruct then open_struct_to_hash(value)
when Array then value.map { |v| open_struct_to_hash(v) }
else value
end
end
hash
end
答案 2 :(得分:1)
这是从lancegatlin的答案修改而来的另一种方法。还将方法添加到OpenStruct类本身。
class OpenStruct
def deep_to_h
each_pair.map do |key, value|
[
key,
case value
when OpenStruct then value.deep_to_h
when Array then value.map {|el| el === OpenStruct ? el.deep_to_h : el}
else value
end
]
end.to_h
end
答案 3 :(得分:0)
相同的函数也可以接受数组作为输入
def openstruct_to_hash(object, hash = {})
case object
when OpenStruct then
object.each_pair do |key, value|
hash[key] = openstruct_to_hash(value)
end
hash
when Array then
object.map { |v| openstruct_to_hash(v) }
else object
end
end