将字典转换为基于值的长度列表

3

我有一个字典

d = {1: 3, 5: 6, 10: 2}

我希望将其转换为一个列表,该列表保存字典的键。每个键应重复与其关联值相同次数。
我编写了以下代码来完成此任务:
d = {1: 3, 5: 6, 10: 2}
l = []
for i in d:
    for j in range(d[i]):
        l.append(i)
l.sort()
print(l)

输出:

[1, 1, 1, 5, 5, 5, 5, 5, 5, 10, 10]

但我希望它是一个列表推导式。如何实现呢?

4个回答

2
您可以使用列表推导式来完成这个操作:
[i for i in d for j in range(d[i])]

yields:

[1, 1, 1, 10, 10, 5, 5, 5, 5, 5, 5]

您可以再次排序以获得您正在查找的列表。

2
或者在列表推导式之前对 d 进行排序。对于大型字典,这样做会更快,因为字典中的项比结果列表少。换句话说,[i for i in sorted(d) for j in range(d[i])] - Rory Daulton

1

[k for k,v in d.items() for _ in range(v)]是一个用于Python编程的列表推导式。

如果您想要对结果进行排序,可以使用以下代码:

[k for k,v in sorted(d.items()) for _ in range(v)]


1
一种方法是使用 itertools.chain 将子列表粘合在一起。
>>> list(itertools.chain(*[[k]*v for k, v in d.items()]))
[1, 1, 1, 10, 10, 5, 5, 5, 5, 5, 5]

如果你正在处理一个非常大的字典,那么你可以使用itertools.chain.from_iterableitertools.repeat来避免构建子列表。

>>> list(itertools.chain.from_iterable(itertools.repeat(k, v) for k, v in d.items()))
[1, 1, 1, 10, 10, 5, 5, 5, 5, 5, 5]

使用包含两个循环的列表推导式处理非常大的字典时的比较时间:

>>> d = {i: i for i in range(100)}
>>> %timeit list(itertools.chain.from_iterable(itertools.repeat(k, v) for k, v in d.items()))
10000 loops, best of 3: 55.6 µs per loop
>>> %timeit [k for k, v in d.items() for _ in range(v)]
10000 loops, best of 3: 119 µs per loop

不清楚您是否需要对输出进行排序(您的示例代码未对其进行排序),如果需要,则只需预先对 d.items() 进行排序即可。

# same as previous examples, but we sort d.items()
list(itertools.chain(*[[k]*v for k, v in sorted(d.items())]))

1

Counter.elements()方法正好可以做到这一点:

from collections import Counter

d = {1: 3, 5: 6, 10: 2}
c = Counter(d)
result = list(c.elements())
print(result)
# [1, 1, 1, 5, 5, 5, 5, 5, 5, 10, 10]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接