我可以在列表推导式中展平包含字典和字典列表的列表吗?

时间:2020-12-27 13:06:29

标签: python-3.x list-comprehension

我有一个函数可以根据传递的参数返回字典或字典列表。下面提供了 MWE:

def do_something(condition: bool):
    if not condition:
        return {"foo": "bar"}
    return [{"foo": "bar"}, {"foo": "bar"}]

my_array = [False, False, True, False]

result = [do_something(i) for i in my_array]
print(result)

我想要做的是让 result 包含单个字典的列表,而不是让某些元素成为字典的列表。所以目前这段代码的结果是:

[{'foo': 'bar'}, {'foo': 'bar'}, [{'foo': 'bar'}, {'foo': 'bar'}], {'foo': 'bar'}]']

但我希望结果是:

[{'foo': 'bar'}, {'foo': 'bar'}, {'foo': 'bar'}, {'foo': 'bar'}, {'foo': 'bar'}]

有什么方法可以使用列表推导来实现这个结果,还是我需要使用 for 循环并随时附加到列表中?

我唯一的想法是看看是否有一种方法可以使用 * 运算符解压缩列表,但这不起作用:

return *[{"foo": "bar"}, {"foo": "bar"}  # Can't used starred expression here.

更新 我在此线程中标记了一个已接受的答案,但通过使用 itertools.chain.from_iterable()

获得了相同的结果

所以我的代码现在是:

import itertools  # Extra import I needed
result = list(
    itertools.chain.from_iterable([do_something(i) for i in my_array])
)

2 个答案:

答案 0 :(得分:1)

你可以试试这个

from collections import Iterable

def flatten(lst):
    for elm in lst:
        if isinstance(elm, Iterable) and not isinstance(elm, (str, bytes, dict)):
            yield from flatten(elm)
        else:
            yield elm
        
l = [{'foo': 'bar'}, {'foo': 'bar'}, [{'foo': 'bar'}, {'foo': 'bar'}], {'foo': 'bar'}]
flatten = list(flatten(l))

输出:[{'foo': 'bar'}, {'foo': 'bar'}, {'foo': 'bar'}, {'foo': 'bar'}, {'foo' : 'bar'}]

如果您不希望 dict 对象出现在扁平化列表中,那么您可以从 isinstance() 检查中删除 dict

答案 1 :(得分:1)

如果您的 Python 是 3.8 或更高版本:

def do_something(condition: bool):
    if not condition:
        return {"foo": "bar"}
    return [{"foo": "bar"}, {"foo": "bar"}]

my_array = [False, False, True, False]

[(result := []) if i is None 
else [result.append(do_something(j)) if not j 
else result.extend(do_something(j)) 
for j in i] 
for i in (None, my_array)]

print(result) 
#[{'foo': 'bar'}, {'foo': 'bar'}, {'foo': 'bar'}, {'foo': 'bar'}, {'foo': 'bar'}]