枚举列表中的唯一字符串

时间:2013-09-16 10:29:40

标签: python list python-2.7

免责声明:我不是一位经验丰富的Python用户。

我遇到了一个任务,现在我正试图找出用Python做的最优雅的方法。

这是任务本身:给定list个字符串返回int s列表(每个int从0到N - 1,其中N是唯一字符串的数量列表),其中每个int对应于初始列表中的某个字符串。相同的字符串应该映射到相同的数字,不同的字符串 - 不同的数字。

我提出的第一件事似乎“有点”过于复杂:

a = ["a","b","a","c","b","a"]
map(lambda x: dict(map(lambda x: reversed(x), enumerate(set(a))))[x], a)

以上代码的结果:

[0, 2, 0, 1, 2, 0]

5 个答案:

答案 0 :(得分:4)

您可以使用dict和list comprehensions:

>>> a = ["a","b","a","c","b","a"]
>>> d = {x:i for i, x in enumerate(set(a))}
>>> [d[item] for item in a]
[0, 2, 0, 1, 2, 0]

保留订单:

>>> seen = set()
>>> d = { x:i for i, x in enumerate(y for y in a
                                       if y not in seen and not seen.add(y))}
>>> [d[item] for item in a]
[0, 1, 0, 2, 1, 0]

上述词典理解相当于:

>>> seen = set()
>>> lis = []
for item in a:
    if item not in seen:
        seen.add(item)
        lis.append(item)
...         
>>> lis
['a', 'b', 'c']
>>> d = {x:i for i,x in enumerate(lis)}

答案 1 :(得分:2)

我认为如果要保留接近字符的顺序,使用set的方法可能会导致错误。实际上,您可以在示例中看到它 - 'b'得到索引2而不是1。如果您想保留订单,可以使用OrderedDict

>>> a = ["a","b","a","c","b","a"]
>>> d = {x:i for i, x in enumerate(OrderedDict(izip(a, a)).values())}
>>> [d[x] for x in a]
[0, 1, 0, 2, 1, 0]

答案 2 :(得分:1)

强调可读性,而不是速度:我会使用列表index方法列表理解:

>>> a = ["a","b","a","c","b","a"]
>>> b = list(set(a))
>>> c = [b.index(x) for x in a]
>>> c
[0, 2, 0, 1, 2, 0]

答案 3 :(得分:0)

首先从列表中获取唯一的字符串并枚举它,因此每个字符串都有一个数字(从0到N-1)。然后为每个字符串获取此值,并将其放入列表中。以下是一行:

a = ["a","b","a","c","b","a"]
[{s:i for i, s in enumerate(set(a))}[s] for s in a]

答案 4 :(得分:0)

您也可以使用defaultdict并计算迭代器。

>>> from collections import defaultdict
>>> from itertools import count
>>> a = ["a","b","a","c","b","a"]
>>> x = defaultdict(count().next)
>>> [x[i] for i in a]
[0, 1, 0, 2, 1, 0]