代码问题 - 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 字典,而不仅仅是任何可迭代的。因此,您只能将生成器用于内部函数(就像您所做的那样),从而使代码变得不必要地复杂。

相反,我建议只使用这样的东西,它会传递你所有的 asserts:

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()本身。)