Python 将字典排序到列表中
关于字典分类的问题已经很多了,但我找不到正确的答案 我有字典v:Python 将字典排序到列表中,python,list,sorting,dictionary,Python,List,Sorting,Dictionary,关于字典分类的问题已经很多了,但我找不到正确的答案 我有字典v: v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0} 我们必须把字典v变成一个排序列表 lijst(v) = [1.0, -2.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.5] 我已尝试使用此代码: def lijst(x): return sorted(x.items(), key=lambda x: x[1]) 这是我收到的清单: lijst(v) =
v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0}
我们必须把字典v变成一个排序列表
lijst(v) = [1.0, -2.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.5]
我已尝试使用此代码:
def lijst(x):
return sorted(x.items(), key=lambda x: x[1])
这是我收到的清单:
lijst(v) = [(1, -2.0), (0, 1.0), (10, 3.5), (3, 4.0)]
有人知道如何将其转换为按键顺序排序的值列表,并用零填充缺少的值吗?您可以使用
itertools中的chain
尝试此操作:
from itertools import chain
v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0}
final_output = list(chain(*sorted(v.items(), key=lambda x: x[1])))
输出:
[1, -2.0, 0, 1.0, 10, 3.5, 3, 4.0]
只需使用以展平结果(元组列表):
如果我误解了您最初的请求,并且字典表示“稀疏向量”(其中键是索引),您可以简单地填充一个只包含零的列表:
>>> res = [0.0]*(max(v)+1) # create a dummy list containing only zeros
>>> for idx, val in v.items(): # populate the requested indices
... res[idx] = val
>>> res
[1.0, -2.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.5]
或者,如果您有NumPy,也可以避免for
-循环:
>>> import numpy as np
>>> arr = np.zeros(max(v)+1)
>>> arr[list(v.keys())] = list(v.values())
>>> arr
array([ 1. , -2. , 0. , 4. , 0. , 0. , 0. , 0. , 0. , 0. , 3.5])
最后一种方法依赖于这样一个事实,即即使键
和值
的顺序是任意的,但只要不修改字典,它们直接对应:
键和值以非随机的任意顺序迭代,在Python实现中有所不同,并且取决于字典的插入和删除历史如果对键、值和项视图进行迭代,而不对字典进行任何修改,则项的顺序将直接对应。
Source连接(键、值)对的一种方法是使用带有初始值的sum()
:
>>> sum(sorted(v.items(), key=lambda x:x[1]), ())
(1, -2.0, 0, 1.0, 10, 3.5, 3, 4.0)
这将返回一个元组。如果您确实需要列表,请将其传递给list()
另一方面,@MSeifert在评论中正确指出,这几乎肯定具有O(n**2)时间复杂性,而list(chain(…)
可能是摊销线性的
v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0}
print sorted(v.values())
结果
[-2.0, 1.0, 3.5, 4.0]
您可以使用列表理解来实现您想要的,例如:
from scipy.sparse import dok_matrix
v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0}
m = dok_matrix((11,1))
m.update(v)
如果要为不可用的项目保留0.0
占位符:
[v.get(i, 0.0) for i in range(max(v.keys())+1)]
输出:
[1.0, -2.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.5]
[1.0, -2.0, 4.0, 3.5]
如果您不想要0.0
占位符,可以使用:
[v.get(i) for i in range(max(v.keys())+1) if v.get(i) is not None]
输出:
[1.0, -2.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.5]
[1.0, -2.0, 4.0, 3.5]
说明:
当您使用range()
时,它将生成一个排序列表,这样您就不必担心排序问题,然后它将尝试根据该列表从字典中获取项目。在第一个示例中,如果键不存在,将返回0.0
,而在第二个示例中,将返回None
,并且将由于表达式中的if语句而被忽略
编辑:
如Christian所述,为了提高效率,您可以将第二个选项更改为:
[v[i] for i in range(max(v.keys())+1) if i in v]
这将避免调用v.get(i)
两次。另一个选项是使用从产生的语法:
警告:请注意,在列表理解中以这种方式使用yield from
可能不是“官方语法”和某些语法(包括Guido)。这不是严格地回答问题,而是试图理解您可能试图实现的目标。如果您正试图实现稀疏向量,在花时间在新的实现上之前,您可能需要研究一下
例如:
from scipy.sparse import dok_matrix
v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0}
m = dok_matrix((11,1))
m.update(v)
稀疏矩阵的优点是(取决于非零元素的分数),它们可能占用更少的内存和/或允许更快的计算。请注意,这将(可能)具有O(n**2)
运行时行为。@MSeifert:很好,谢谢。我已经在答案中添加了警告。您的第二个解决方案必须调用两次dict.get
,因此效率低下。相反,您可以简单地测试i
是否在v
的键中,然后添加v[i]
如果是:[v[i]表示i在范围内(如果i在v中,则最大值(v.keys())+1)。
。这种方法的速度快了大约两倍。尽管它是一种有趣的替代方法(+1):由于它的副作用,使用列表理解通常不被认为是pythonic。@mseivert真的吗?我不认为这是在使用副作用列表。我的理解是,[(从tup得到的收益)for tup in lst]
返回一个生成器表达式。这被传递到list()
,它在生成器上重复调用next
,并且每次都返回(从tup获得的收益)
。正因为如此,它似乎是在使用实际的列表理解,而不仅仅是它的副作用。如果我错了,请纠正我?我不太确定,但列表理解实际上创建了一个包含None
s的列表(即使您从未看到它们,因为它们最终附加到StopIteration
),外部的list()
只捕获生成的值。但是我已经(但我不清楚哪个部分是“buggy部分”),所以我肯定不确定它是否应该作为一种官方支持的语法来提倡。@MSeifert啊,我明白了。谢谢我将在我的回答中添加一条关于理解中的收益的性质的警告。注意:这在3.8中不起作用,在3.7FYI中被弃用,原因是您得到的答案给出了非常不同的结果(即,一些给出的结果[1.0,-2.0,0.0,4.0,0.0,0.0,0.0,0.0,0.0,3.5]
,一些给出[1,-2.0,0,1.0,10,3.5,3,4.0]
)是“压平列表”的意思与您实际寻找的答案非常不同。如果您将最后一个问题改为“有人知道如何将其转换为按键排序的值列表,并用零填充缺少的值吗?”@SethMMorton谢谢,我已经编辑了这个问题。