9

我有一个值列表,我想将它们放在一个字典中,该字典会将每个值映射到它的索引。

我可以这样做:

>>> t = (5,6,7)
>>> d = dict(zip(t, range(len(t))))
>>> d
{5: 0, 6: 1, 7: 2}

这还不错,但我正在寻找更优雅的东西。

我遇到了以下情况,但它与我需要的相反:

>>> d = dict(enumerate(t))
>>> d
{0: 5, 1: 6, 2: 7}

请分享您的解决方案,
谢谢

编辑:Python 2.6.4

对于包含 1000 个元素的列表,dict(zip) 版本是最快的,生成器和列表理解版本几乎相同,它们慢了约 1.5 倍,而功能映射(反转)则慢得多。

$ python -mtimeit -s"t = range(int(1e3))" "d = dict(zip(t, range(len(t))))"
1000 个循环,最好的 3:每个循环 277 微秒

$ python -mtimeit -s"t = range(int(1e3))" "d = dict([(y,x) for x,y in enumerate(t)])"
1000 个循环,最好的 3 个:426 usec per环形

$ python -mtimeit -s"t = range(int(1e3))" "d = dict((y,x) for x,y in enumerate(t))"
1000 个循环,最好的 3 个:每个循环 437 usec

$ python -mtimeit -s"t = range(int(1e3))" "d = dict(map(reversed, enumerate(t)))"
100 个循环,最好的 3 个:每个循环 3.66 毫秒

我尝试对更长和更短的列表(1e2、1e4、1e5)运行相同的测试,并且每个循环的时间与列表的长度成线性关系。

有人可以计时 py 2.7+ 版本吗?

4

6 回答 6

14

您可以使用列表推导(或生成器,取决于您的 python 版本)为您的第二个示例执行简单的就地交换。


使用列表推导:

d = dict([(y,x) for x,y in enumerate(t)])

使用生成器表达式(Python 2.4 及更高版本):

d = dict((y,x) for x,y in enumerate(t))
于 2010-05-14T03:30:42.813 回答
14

在 Python2.7+ 中可以这样写

>>> t = (5,6,7)
>>> d = {x:i for i,x in enumerate(t)}
>>> print d
{5: 0, 6: 1, 7: 2}
于 2010-05-14T03:48:13.540 回答
4
>>> dict((x,i) for i,x in enumerate(t))
{5: 0, 6: 1, 7: 2}
>>>
于 2010-05-14T03:32:40.940 回答
2

您的所有元素都是独一无二的吗(即您的列表永远不会是 5、6、7、7)?dict 解决方案仅在您的所有元素都是唯一的情况下才有效。

通过存储索引,您实际上是在复制信息,因为您可以简单地查询列表中项目的当前索引。复制信息通常不是最好的主意,因为它允许一组数据与另一组数据不同步。

如果正在修改列表,也没有什么可以阻止您意外地将相同的索引分配给多个项目。

当您可以简单地从列表中获取索引时,为什么要尝试存储索引值?

于 2010-05-14T03:37:08.353 回答
2

正如每个人都已经写过的,在 Python 2.6 中,我认为以下是最 Python 的:

>>> dict((x, i) for i, x in enumerate(t))
{5: 0, 6: 1, 7: 2}

不过,在功能狂热的时刻,我会写:

>>> dict(map(reversed, enumerate(t)))
{5: 0, 6: 1, 7: 2}
于 2010-05-14T07:12:12.347 回答
0

我最喜欢 dict(zip(t, range(len(t))))。

于 2010-05-14T03:38:51.020 回答