将字典排序到列表中

时间:2017-08-02 18:31:42

标签: 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) = [(1, -2.0), (0, 1.0), (10, 3.5), (3, 4.0)]

是否有人知道如何将其转换为按其键排序的值列表,缺失值填充为零?

7 个答案:

答案 0 :(得分:11)

只需使用itertools.chain.from_iterable来展平您的结果(元组列表):

>>> import itertools

>>> list(itertools.chain.from_iterable([(1, -2.0), (0, 1.0), (10, 3.5), (3, 4.0)]))
[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])

最后一种方法依赖于以下事实:即使keysvalues的顺序是任意的,只要没有修改字典,它们就会直接对应:

  

键和值以任意顺序迭代,这是非随机的,在Python实现中各不相同,并且取决于字典的插入和删除历史。 如果重复了键,值和项目视图而没有对字典进行干预修改,则项目的顺序将直接对应。

来源4.10.1. Dictionary view objects

答案 1 :(得分:6)

您可以使用chain中的itertools来尝试此操作:

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]

答案 2 :(得分:5)

连接(键,值)对的一种方法是使用带有初始值的sum()

>>> sum(sorted(v.items(), key=lambda x:x[1]), ())
(1, -2.0, 0, 1.0, 10, 3.5, 3, 4.0)

这会返回一个元组。如果您确实需要列表,请将其传递给list()

P.S。正如@MSeifert在评论中正确指出的那样,这几乎肯定具有O(n ** 2)时间复杂度,而list(chain(...))可能是线性摊销。

答案 3 :(得分:4)

另一种选择是使用yield from语法introduced in Python 3.3

>>> lst = [(1, -2.0), (0, 1.0), (10, 3.5), (3, 4.0)]
>>> list([(yield from tup) for tup in lst])
[1, -2.0, 0, 1.0, 10, 3.5, 3, 4.0]
>>> 

警告:请注意,在列表理解中使用yield from这种方式可能不是“官方语法”和一些(包括Guido)consider it a bug

答案 4 :(得分:2)

您可以使用list-comprehension来实现您的目标,例如:

如果您希望将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]

如果您不想要0.0占位符,您可以使用:

[v.get(i) for i in range(max(v.keys())+1) if v.get(i) is not None]

输出:

[1.0, -2.0, 4.0, 3.5]

<强>解释

当您使用range()时,它会生成一个排序列表,因此您不必担心排序,然后它会尝试按照该列表从字典中获取项目。在第一个示例中,如果密钥不存在,则将返回0.0,而在第二个示例中将返回None,并且由于表达式中的if-statement将被忽略

修改

正如克里斯蒂安提到的,你可以改变第二个选项以提高效率:

[v[i] for i in range(max(v.keys())+1) if i in v]

这样可以避免两次调用v.get(i)

答案 5 :(得分:0)

这不是严格地回答问题,而是试图了解你可能想要实现的目标。如果您正在尝试实现稀疏向量,那么在花时间在新实现上之前,您可能需要查看scipy.sparse

例如:

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)

稀疏矩阵的优点是(取决于非零元素的分数)它们可能占用更少的内存和/或允许更快的计算。

答案 6 :(得分:-1)

dom: 'Bfrtip',

结果

v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0}
print sorted(v.values())