Python 将字典排序到列表中

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:

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谢谢,我已经编辑了这个问题。