免责声明:我不是一位经验丰富的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]
答案 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]