从 Python 列表创建字典数组
Posted
技术标签:
【中文标题】从 Python 列表创建字典数组【英文标题】:Create an array of dictionaries from a Python list 【发布时间】:2019-06-02 16:29:21 【问题描述】:我想将散布值列表转换为字典数组。
我正在尝试在 Python 中创建一个能够与 JSON API 一起使用的预测值列表。拿到字典后,我会在上面使用json.dumps
。
my_list = [35, 2.75, 67, 3.45] # in form of: (value, score, value, score)
理想的结果:
my_array_of_dicts = ['value':35, 'score':2.75, 'value':67 'score':3.45]
这是我尝试过的。
第一次尝试:
d = dict(zip(my_list[::2], my_list[1::2]))
它会产生...
> 35: 2.75,
67: 3.45
我不确定如何获取自定义键。或者将每一对作为自己的字典。
第二次尝试:
['value':i, 'score':i for i in my_list]]
> ['value':35, 'score':35, 'value':2.75, 'score':2.75,
'value':67, 'score':67, 'value':3.45, 'score':3.45]
它很接近,但它并没有考虑到每一秒的值都是一个分数。
【问题讨论】:
【参考方案1】:你真的很接近zip
版本。您只需要制作对象并指定键即可。
my_list = [35, 2.75, 67, 3.45]
['value': v, 'score': s for v, s in zip(my_list[::2], my_list[1::2])]
结果:
['value': 35, 'score': 2.75, 'value': 67, 'score': 3.45]
【讨论】:
【参考方案2】:在第二次尝试中,得分:i + 1。在循环中执行 for i in range(0, len(my_list), 2)。
【讨论】:
【参考方案3】:d = map(dict, map(lambda t:zip(('value','score'),t), zip(my_list[::2], my_list[1::2])))
print(list(d))
【讨论】:
【参考方案4】:试试这个:
my_list = [35, 2.75, 67, 3.45]
list_of_dicts = ['value': k, 'score': v for k, v in zip(iter(my_list), iter(my_list))]
print(list_of_dicts)
输出:
['value': 35, 'score': 2.75, 'value': 67, 'score': 3.45]
我的解决方案与其他使用列表切片的解决方案之间的时间比较:
In [1]: my_list = [35, 2.75, 67, 3.45] * 100 # making it longer for better testing results
In [2]: def zip_with_slice():
...: return ['value': v, 'score': s for v, s in zip(my_list[::2], my_list[1::2])]
...:
In [3]: def zip_with_iter():
...: return ['value': k, 'score': v for k, v in zip(iter(my_list), iter(my_list))]
...:
In [4]: %timeit zip_with_slice()
56.5 µs ± 1.27 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [5]: %timeit zip_with_iter()
93 µs ± 2.99 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
如您所见,我使用迭代器的解决方案比使用切片的解决方案快很多(5-6 倍)。
【讨论】:
@aws_apprentice 您必须拥有一台更快的计算机,因为我的测试显示您在57.8 µs
上进行了编辑。
@aws_apprentice 我找到了原因。我正在使用原始列表 * 100
进行测试以获得更准确的结果,而您正在使用原始列表进行测试。这是有道理的,因为您的解决方案看起来不像是改进。
@aws_apprentice 您确定您使用的是新的、更长的列表吗?此外,您的 timeit
似乎不公平,因为您事先进行了实际计算。【参考方案5】:
单行使用理解:
['value': k, 'score': v for k, v in [my_list[i: i + 2] for i in range(0, len(my_list), 2)]]
['score': 2.75, 'value': 35, 'score': 3.45, 'value': 67]
使用您最初的尝试:
['value': k, 'score': v for k,v in zip(my_list[::2], my_list[1::2])]
另一种更详细的方式
from operator import itemgetter
getters = [itemgetter(slice(i, i + 2)) for i in range(0, len(my_list), 2)]
vals = [g(my_list) for g in getters]
def score_vals(s):
k, v = s
return 'value': k, 'score': v
list(map(score_vals, vals))
【讨论】:
%timeit list(map(score_vals, vals))
实际上并没有为整个计算计时,只是其中的一小部分。【参考方案6】:
使用列表理解:
>>> my_list = [35, 2.75, 67, 3.45]
>>> my_dict = ['value': my_list[i], 'score': my_list[i+1] for i in range(0, len(my_list), 2)]
>>> my_dict
['score': 2.75, 'value': 35, 'score': 3.45, 'value': 67]
【讨论】:
【参考方案7】:另一种方法,使用带有参数的dict
(**kwargs**
):
>>> my_list = [35, 2.75, 67, 3.45]
>>> [dict(value=x,score=y) for x,y in zip(my_list[::2], my_list[1::2])]
['value': 35, 'score': 2.75, 'value': 67, 'score': 3.45]
>>>
【讨论】:
【参考方案8】:class my_dictionary(dict):
# __init__ function
def __init__(self):
self = dict()
# Function to add key:value
def add(self, key, value):
self[key] = value
# Main Function
dict_obj = my_dictionary()
然后您可以使用以下代码将保存在tmpkey
和tmpvalue
中的值分配给字典中的键值对。
dict_obj.key = tmpkey
dict_obj.value = tmpvalue
dict_obj.add(dict_obj.key, dict_obj.value)
而要创建字典列表,您只需创建一个空列表并在列表的每个元素中分配字典的副本。
dicMatrix = []
dictionary_copy = dict_obj.copy()
dicMatrix.append(dictionary_copy)
通过这种方式,您的字典将动态增长,制作字典副本的原因是,如果您每次将新值添加到列表中时都更改字典的值,否则对字典的引用将被分配到列表中。
【讨论】:
以上是关于从 Python 列表创建字典数组的主要内容,如果未能解决你的问题,请参考以下文章