[英]How to convert a dict to list of dicts in Python?
我有以下問題:我想提供一個簡單的函數,它遍歷參數集列表並對所有集合執行相同的操作。 這個想法是將標量值或任何可迭代對象作為 kwarg 傳遞給函數,然后該函數生成每組 kwarg,然后對它們調用操作。
def simple_function(**kwargs):
list_of_kwargs = convert_kwargs(kwargs)
return [my_action(**kwargs_set) for kwargs_set in list_of_kwargs]
因此,我發現很難將convert_kwargs
實現為高效和通用的。 我需要完成的一些示例測試用例:
class ConvertParamsTestCase(unittest.TestCase):
def test_convert_kwargs_no_list(self):
kwargs = {'arg1': 1, 'arg2': "string", 'arg3': None}
self.assertDictEqual(kwargs, convert_kwargs(kwargs))
def test_convert_kwargs_all_lists(self):
kwargs = {'arg1': [1, 2], 'arg2': ["string", "str"], 'arg3': [None, None]}
expected = [{'arg1': 1, 'arg2': "string", 'arg3': None}, {'arg1': 2, 'arg2': "str", 'arg3': None}]
self.assertListEqual(expected, convert_kwargs(kwargs))
def test_convert_kwargs_one_is_string(self):
kwargs = {'arg1': [1, 2], 'arg2': "string", 'arg3': [None, None]}
expected = [{'arg1': 1, 'arg2': "string", 'arg3': None}, {'arg1': 2, 'arg2': "string", 'arg3': None}]
self.assertListEqual(expected, convert_kwargs(kwargs))
def test_convert_kwargs_one_is_iterator(self):
kwargs = {'arg1': range(1, 3), 'arg2': "string", 'arg3': [None, None]}
expected = [{'arg1': 1, 'arg2': "string", 'arg3': None}, {'arg1': 2, 'arg2': "string", 'arg3': None}]
self.assertListEqual(expected, convert_kwargs(kwargs))
我已經檢查過但沒有成功: list of dicts to/from dict of list
我的主要問題是:
我將不勝感激任何想法!
您可以檢查字符串並為它們做一些不同的事情:
if isinstance(something,str):
do_thing_with_string(something)
else:
do_thing_with_iterable(something)
並且您不應該能夠檢查生成器的長度:
def gen():
i = 0
while True:
yield i
i+=1
endless = gen()
for _ in range(20):
print(next(endless)) # works ... while len(endless) won't
您可以將其用作起始塊。 代碼 get 是一個字典,在里面查找最長的列表並從中創建一組字典。 您需要增強它以處理列表列表。 如果你給出一個字符串,它將出現在任何列表中:
def convert(paramdict):
l = []
# lists ordered by lenght, longest first, strings in the back
params = sorted(paramdict.items(),
key=lambda x:len(x[1]) if isinstance(x[1],list) else -1,
reverse=True)
# max number of inner dicts to create
maxone = len(params[0][1]) if isinstance(params[0][1],list) else 1
for n_th in range(maxone):
l.append({})
for k,value in params:
if isinstance(value,list):
if len(value) > n_th:
l[-1][k] = value[n_th]
# add other things here: tuple, set, generator
# it might be easiest to convert f.e. set/tuple to list
# for generator you would need to takewhile() from it until
# you got as much as you need
else:
l[-1][k] = value
return l
print(convert( {'arg1': [1, 2], 'arg2': ["string", "str", "s"],
'arg3': [None, None], 'arg4': "some lengthy strings"} ) )
輸出:
[{'arg2': 'string', 'arg1': 1, 'arg3': None, 'arg4': 'some lengthy strings'},
{'arg2': 'str', 'arg1': 2, 'arg3': None, 'arg4': 'some lengthy strings'},
{'arg2': 's', 'arg4': 'some lengthy strings'}]
如果列表太短,它將從輸出字典中丟失。 在斷言“相等”時,您仍然必須處理排序,以防此算法確實以不同的順序創建內部字典。
要以通用方式解決問題,請考慮使所有argx
值符合列表類型。
如果您定義一個協議,其中所有參數都是值列表:
kwargs = {
'arg1': range(0,3), 'arg2': ["s1"]*3, 'arg3': [10, 20]
}
給予:
[{'arg1': 0, 'arg2': 's1', 'arg3': 10},
{'arg1': 1, 'arg2': 's1', 'arg3': 20},
{'arg1': 2, 'arg2': 's1', 'arg3': None}]
這是一個解決方案:
kwargs = {'arg1': range(0, 3), 'arg2': ["s1"]*3, 'arg3': [10, 20]}
max_args = max([len(kwargs[key]) for key in kwargs])
list_of_kwargs = [{k: kwargs[k][index] if index < len(
kwargs[k]) else None for k in kwargs} for index in range(max_args)]
請注意,傳遞相同的字符串值是["value"]*3
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.