oar*_*ish 30 python dictionary list python-3.x
我有一个像这样的dicts列表:
l = [{'name': 'foo', 'values': [1,2,3,4]}, {'name': 'bar', 'values': [5,6,7,8]}]
Run Code Online (Sandbox Code Playgroud)
我想获得这种形式的输出:
>>> [('foo', 'bar'), ([1,2,3,4], [5,6,7,8])]
Run Code Online (Sandbox Code Playgroud)
但是缺乏for环比和append我没有看到解决方案.有比这更聪明的方法吗?
names = []
values = []
for d in l:
names.append(d['name'])
values.append(d['values'])
Run Code Online (Sandbox Code Playgroud)
eyl*_*esc 33
使用生成器表达:
l = [{'name': 'foo', 'values': [1,2,3,4]}, {'name': 'bar', 'values': [5,6,7,8]}]
v = [tuple(k["name"] for k in l), tuple(k["values"] for k in l)]
print(v)
Run Code Online (Sandbox Code Playgroud)
输出:
[('foo', 'bar'), ([1, 2, 3, 4], [5, 6, 7, 8])]
Run Code Online (Sandbox Code Playgroud)
Kev*_*vin 24
如果我正在编写此代码供公众使用,我会使用列表理解(很像eyllanesc的).但只是为了好玩,这里是一个不使用任何fors 的单行.
>>> l = [{'name': 'foo', 'values': [1,2,3,4]}, {'name': 'bar', 'values': [5,6,7,8]}]
>>> list(zip(*map(dict.values, l)))
[('foo', 'bar'), ([1, 2, 3, 4], [5, 6, 7, 8])]
Run Code Online (Sandbox Code Playgroud)
(请注意,这只有在字典保留插入顺序时才能可靠地工作,而在所有版本的Python中都不是这样.CPython 3.6将其作为实现细节,但它仅保证3.7的行为.)
快速细分过程:
dict_values对象,该对象是一个包含dict所有值的iterable.map获取每个字典l并在其上调用dict.values,返回一个可迭代的dict_values对象.zip(*thing)是一个经典的"转置"配方,它采用可迭代的迭代,并有效地对角翻转它.例如[[a,b],[c,d]]变为[[a,c],[b,d]].这会将所有名称放入一个元组,将所有值放入另一个元组中.list 将zip对象转换为列表.jpp*_*jpp 10
您可以使用operator.itemgetter以保证值的排序:
from operator import itemgetter
fields = ('name', 'values')
res = list(zip(*map(itemgetter(*fields), L)))
print(res)
[('foo', 'bar'), ([1, 2, 3, 4], [5, 6, 7, 8])]
Run Code Online (Sandbox Code Playgroud)
如果,假设Python 3.6+,您无法保证在输入列表中对字典进行适当的插入排序,则需要如上所述明确定义顺序.
性能
虽然"元组理解"列表有效,但在查询多个字段时会变得难以理解且效率低下:
from operator import itemgetter
n = 10**6
L = [{'name': 'foo', 'values': [1,2,3,4], 'name2': 'zoo', 'name3': 'xyz',
'name4': 'def'}, {'name': 'bar', 'values': [5,6,7,8], 'name2': 'bart',
'name3': 'abc', 'name4': 'ghi'}] * n
%timeit [tuple(k["name"] for k in L), tuple(k["values"] for k in L),\
tuple(k["name2"] for k in L), tuple(k["name3"] for k in L),
tuple(k["name4"] for k in L)]
%timeit fields = ('name', 'values', 'name2', 'name3' ,'name4');\
list(zip(*map(itemgetter(*fields), L)))
1 loop, best of 3: 1.25 s per loop
1 loop, best of 3: 1.04 s per loop
Run Code Online (Sandbox Code Playgroud)
这可能不是你想到的那样,但对于像这样的表格数据,我发现pandas从长远来看,这通常是最好的解决方案:
>>> import pandas as pd
>>> l = [{'name': 'foo', 'values': [1,2,3,4]}, {'name': 'bar', 'values': [5,6,7,8]}]
>>> df = pd.DataFrame(l)
name values
0 foo [1, 2, 3, 4]
1 bar [5, 6, 7, 8]
Run Code Online (Sandbox Code Playgroud)
通常,您可以直接使用数据框来执行任何操作,但您也可以将其转换为基于列表的数据结构:
>>> df['name'].tolist(), df['values'].tolist()
(['foo', 'bar'], [[1, 2, 3, 4], [5, 6, 7, 8]])
Run Code Online (Sandbox Code Playgroud)