簡體   English   中英

如何在列表理解中解包列表

[英]how can unpack a list in list comprehension

我有一個字典列表,每個字典都可以嵌套一個字典列表,如下所示:

mydictlist = [{'name':'foo'}, {'name':'bar','next-level':[{'name':'next-level-foo'}, {'name':'next-level-bar'}] } ]

我試圖在列表理解中展平某種屬性,如名稱,如下所示:

flattened = [ *['{}_{}'.format(iter['name'],next['name']) for next in iter] if 'next-level' in iter else '{}'.format(iter['name']) for iter in mydictlist]

得到類似的東西:

['foo', 'bar_next-level-foo', 'bar_next-level-bar']

但這會導致錯誤。? 我可以使用 for 和 if 沒有列表理解(並且已經做到了)但我想知道使用列表(或元組解包)和列表理解的正確語法是什么?

mydictlist = [{'name':'foo'}, {'name':'bar','next-level':[{'name':'next-level-foo'}, {'name':'next-level-bar'}] } ]

def flatten(currlist, prefix = None, delimiter = "_"):
    l = []
    for x in currlist:
        print (l)
        if "next-level" in x:
            if prefix:
                prefix = delimiter.join([prefix, x["name"]])
            else:
                prefix = x["name"]
            c = flatten(currlist=x["next-level"], prefix=prefix, delimiter=delimiter)
            l.extend(c)
        else:
            if not prefix:
                item = x["name"]
            else:
                item = delimiter.join([prefix, x["name"]])
            l.append(item)
    return l

flatten(currlist=mydictlist)

這里是你想要的差不多

result = [x['name'] if "next-level" not in x else [ j['name'] for j in x['next-level']] for x in mydictlist ]
print(result)
# output: ['foo', ['next-level-foo', 'next-level-bar']]
result2 = []
def flettern_list(lst):
    for s in lst:
        if isinstance(s, str):
            result2.append(s)
        elif isinstance(s, list):
            flettern_list(s)
flettern_list(result)
print(result2) #output: ['foo', 'next-level-foo', 'next-level-bar']

這是一個相當通用的解決方案,它將在任何類型的 dict 和 list 組合中遞歸。 這將返回名稱值的平面列表。

def get_leafs_as_list(obj, key):
    l = []
    if isinstance(obj, list):
        for v in obj:
            l.extend(get_leafs_as_list(v, key))
    elif isinstance(obj, dict):
        for k, v in obj.items():
            if k == key:
                l.append(v)
            else:
                l.extend(get_leafs_as_list(v, key))
    return l

mydictlist = [{'name':'foo'}, {'name':'bar','next-level':[{'name':'next-level-foo'}, {'name':'next-level-bar'}] } ]

print(get_leafs_as_list(mydictlist, 'name'))

這將返回:

['foo', 'bar', 'next-level-foo', 'next-level-bar']

我能做的最接近的是在必要時提供“假”第二級,然后忽略它:

mydictlist = [{'name':'foo'}, {'name':'bar','next-level':[{'name':'next-level-foo'}, {'name':'next-level-bar'}] } ]

flattened = [ '{}_{}'.format(item['name'],next['name']) if next['name'] else item['name'] for item in mydictlist for next in (item['next-level'] if 'next-level' in item else  [{'name':None}]) ]

Output:

 ['foo', 'bar_next-level-foo', 'bar_next-level-bar']

在列表理解中似乎沒有條件循環的方法。 因此,如果有兩個for -s,它們都將運行,但可以有條件地生成第二個循環的“主題”(最初我使用 lambda 執行此操作,但顯然帶括號的表達式就足夠了)。

您的嘗試有一個錯誤, for next in iter應該是for next in iter['next-level'] (另外, iter()是一個內置的 function,所以我將它重命名為item )。
如果你嘗試了一些不那么雄心勃勃的事情,你會遇到一個明確的錯誤信息: iterable unpacking cannot be used in comprehension

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM