从 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()

然后您可以使用以下代码将保存在tmpkeytmpvalue中的值分配给字典中的键值对。

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 列表创建字典数组的主要内容,如果未能解决你的问题,请参考以下文章

使用字典 get() 作为函数从地图创建 Python 列表与使用 for 循环创建字典 get() 列表

Python:从父子值列表创建嵌套字典

从 Python 中的 csv 创建字典中的字典列表

python 从两个列表创建字典

python 2.7:从集合列表创建字典

Python:如何从列表中的字典创建 DataFrame 列 [重复]