代码问题 - Flatten dictionary using generator
Code problem - Flatten dictionary using generator
首先,这个post是一个不使用生成器的解决方案:
我有一本字典中的字典。
例如:
{
"name": {
"first": "One",
"last": "Drone"
},
"job": "scout",
"recent": {},
"additional": {
"place": {
"zone": "1",
"cell": "2"}
}
}
结果将是:
{"name/first": "One", #one parent
"name/last": "Drone",
"job": "scout", #root key
"recent": "", #empty dict
"additional/place/zone": "1", #third level
"additional/place/cell": "2"}
我试过用不同的方法解决它,但是键不会 return 如果你能帮我弄清楚如何在那里使用递归。顺便说一句,这是 checkio.org 的练习
def flatten(a):
arr = flatten_dictionary(a)
newDict = {}
for i in arr:
temp = i.split(':')
try:
newDict[temp[0]]=temp[1]
except:
pass
return newDict
def flatten_dictionary(a):
for i in a:
if isinstance(a[i],type(dict)):
yield from(i+'/' + flatten(a[i])) #won't enter this if scope
else:
yield ':'+a[i]
如果你想测试它,这里有一些断言..
assert flatten({"key": "value"}) == {"key": "value"}, "Simple"
assert flatten(
{"key": {"deeper": {"more": {"enough": "value"}}}}
) == {"key/deeper/more/enough": "value"}, "Nested"
assert flatten({"empty": {}}) == {"empty": ""}, "Empty value"
assert flatten({"name": {
"first": "One",
"last": "Drone"},
"job": "scout",
"recent": {},
"additional": {
"place": {
"zone": "1",
"cell": "2"}}}
) == {"name/first": "One",
"name/last": "Drone",
"job": "scout",
"recent": "",
"additional/place/zone": "1",
"additional/place/cell": "2"}
此外,现在这是我的结果:{"":"value"}
第一个问题是,对于 if isinstance(a[i],type(dict))
,您正在测试该项目是否是 type(dict)
的实例,即 type
,而不是 dict
,但确实如此无法解决所有问题。
>>> type(dict)
<type 'type'>
>>> dict
<type 'dict'>
虽然您要求使用生成器的解决方案,但我认为这在这里真的没有意义,因为您想要 return 字典,而不仅仅是任何可迭代的。因此,您只能将生成器用于内部函数(就像您所做的那样),从而使代码变得不必要地复杂。
相反,我建议只使用这样的东西,它会传递你所有的 assert
s:
def flatten(d):
res = {}
for key, val in d.items():
if isinstance(val, dict):
if not val:
res[key] = ""
for k2, v2 in flatten(val).items():
res["%s/%s" % (key, k2)] = v2
else:
res[key] = val
return res
如果你真的想保持内生成器风格,你可以使用这个:
def flatten(d):
return dict(_flatten_gen(d))
def _flatten_gen(d):
for key, val in d.items():
if isinstance(val, dict):
if not val:
yield (key, "")
yield from (("%s/%s" % (key, k2), v2) for k2, v2 in flatten(val).items())
else:
yield (key, val)
请注意,这是生成元组,可以将其直接传递给 dict
构造函数,而不是通过 :
连接然后拆分键和值。 (事实上 ,这样,生成器可能实际上是有意义的,因为如果您只想迭代所有展平的项目并且不需要字典,您可以只调用 _flatten_gen(d)
而不是 flatten(d).items()
本身。)
首先,这个post是一个不使用生成器的解决方案:
我有一本字典中的字典。
例如:
{
"name": {
"first": "One",
"last": "Drone"
},
"job": "scout",
"recent": {},
"additional": {
"place": {
"zone": "1",
"cell": "2"}
}
}
结果将是:
{"name/first": "One", #one parent
"name/last": "Drone",
"job": "scout", #root key
"recent": "", #empty dict
"additional/place/zone": "1", #third level
"additional/place/cell": "2"}
我试过用不同的方法解决它,但是键不会 return 如果你能帮我弄清楚如何在那里使用递归。顺便说一句,这是 checkio.org 的练习
def flatten(a):
arr = flatten_dictionary(a)
newDict = {}
for i in arr:
temp = i.split(':')
try:
newDict[temp[0]]=temp[1]
except:
pass
return newDict
def flatten_dictionary(a):
for i in a:
if isinstance(a[i],type(dict)):
yield from(i+'/' + flatten(a[i])) #won't enter this if scope
else:
yield ':'+a[i]
如果你想测试它,这里有一些断言..
assert flatten({"key": "value"}) == {"key": "value"}, "Simple"
assert flatten(
{"key": {"deeper": {"more": {"enough": "value"}}}}
) == {"key/deeper/more/enough": "value"}, "Nested"
assert flatten({"empty": {}}) == {"empty": ""}, "Empty value"
assert flatten({"name": {
"first": "One",
"last": "Drone"},
"job": "scout",
"recent": {},
"additional": {
"place": {
"zone": "1",
"cell": "2"}}}
) == {"name/first": "One",
"name/last": "Drone",
"job": "scout",
"recent": "",
"additional/place/zone": "1",
"additional/place/cell": "2"}
此外,现在这是我的结果:{"":"value"}
第一个问题是,对于 if isinstance(a[i],type(dict))
,您正在测试该项目是否是 type(dict)
的实例,即 type
,而不是 dict
,但确实如此无法解决所有问题。
>>> type(dict)
<type 'type'>
>>> dict
<type 'dict'>
虽然您要求使用生成器的解决方案,但我认为这在这里真的没有意义,因为您想要 return 字典,而不仅仅是任何可迭代的。因此,您只能将生成器用于内部函数(就像您所做的那样),从而使代码变得不必要地复杂。
相反,我建议只使用这样的东西,它会传递你所有的 assert
s:
def flatten(d):
res = {}
for key, val in d.items():
if isinstance(val, dict):
if not val:
res[key] = ""
for k2, v2 in flatten(val).items():
res["%s/%s" % (key, k2)] = v2
else:
res[key] = val
return res
如果你真的想保持内生成器风格,你可以使用这个:
def flatten(d):
return dict(_flatten_gen(d))
def _flatten_gen(d):
for key, val in d.items():
if isinstance(val, dict):
if not val:
yield (key, "")
yield from (("%s/%s" % (key, k2), v2) for k2, v2 in flatten(val).items())
else:
yield (key, val)
请注意,这是生成元组,可以将其直接传递给 dict
构造函数,而不是通过 :
连接然后拆分键和值。 (事实上 ,这样,生成器可能实际上是有意义的,因为如果您只想迭代所有展平的项目并且不需要字典,您可以只调用 _flatten_gen(d)
而不是 flatten(d).items()
本身。)