用键替换python列表元素

Rac*_*hie 4 python key list

我有一个非唯一字符串列表:

list = ["a", "b", "c", "a", "a", "d", "b"]
Run Code Online (Sandbox Code Playgroud)

我想用一个唯一标识每个字符串的整数键替换每个元素:

list = [0, 1, 2, 0, 0, 3, 1]
Run Code Online (Sandbox Code Playgroud)

该数字无关紧要,只要它是唯一标识符即可.

到目前为止,我所能想到的是将列表复制到一个集合,并使用集合的索引来引用列表.我确信有更好的方法.

sch*_*ggl 10

这将保证唯一性,并且id是连续的,从0以下开始:

id_s = {c: i for i, c in enumerate(set(list))}
li = [id_s[c] for c in list]
Run Code Online (Sandbox Code Playgroud)

另外,您不应该使用'list'变量名称,因为它会影响内置类型list.


And*_*den 5

这是一个使用defaultdict的单通道解决方案:

from collections import defaultdict
seen = defaultdict()
seen.default_factory = lambda: len(seen)  # you could instead bind to seen.__len__

In [11]: [seen[c] for c in list]
Out[11]: [0, 1, 2, 0, 0, 3, 1]
Run Code Online (Sandbox Code Playgroud)

这是一种技巧但值得一提!


@ user2357112在相关问题/答案中建议的另一种方法是增加itertools.count.这允许您只在构造函数中执行此操作:

from itertools import count
seen = defaultdict(count().__next__)  # .next in python 2
Run Code Online (Sandbox Code Playgroud)

这可能是优选的,因为default_factory方法不会seen在全局范围内查找.

  • [`itertools.count().next`也可以](http://stackoverflow.com/questions/18605500/assign-strings-to-ids-in-python/18605520#18605520)为`default_factory`,或者你可以使用`seen = defaultdict(lambda:len(seen))`,因为`seen`不需要存在来创建lambda.我更喜欢`itertools.count().next`到`lambda:len(see)`,因为它不需要在变异操作的中间检查dict的状态,但是任何一个版本都觉得有太多的魔法在继续在`default_factory`中. (3认同)