关于排序字典已经有很多问题,但我无法找到问题的正确答案。
我有字典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)]
是否有人知道如何将其转换为按其键排序的值列表,缺失值填充为零?
答案 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])
最后一种方法依赖于以下事实:即使keys
和values
的顺序是任意的,只要没有修改字典,它们就会直接对应:
键和值以任意顺序迭代,这是非随机的,在Python实现中各不相同,并且取决于字典的插入和删除历史。 如果重复了键,值和项目视图而没有对字典进行干预修改,则项目的顺序将直接对应。
答案 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())