我搜索了一段时间,但没有找到任何解释我正在尝试做的事情。
基本上我有一个字符串“标签”列表,例如[“棕色”,“黑色”,“蓝色”,“棕色”,“棕色”,“黑色”]等。我想要做的是将其转换为整数列表,其中每个标签对应一个整数,所以< / p>
["brown", "black", "blue", "brown", "brown", "black"]
变为
[1, 2, 3, 1, 1, 2]
我查看了枚举函数但是当我给它我的字符串列表(这很长)时,它为每个单独的标签分配了一个int,而不是给同一个标签提供相同的int:
[(1,"brown"),(2,"black"),(3,"blue"),(4,"brown"),(5,"brown"),(6,"black")]
我知道如何通过漫长而繁琐的for循环和if-else检查来做到这一点,但我真的很好奇,如果只用一两行就能有更优雅的方式来做这件事。
答案 0 :(得分:7)
你有非独特的标签;您可以使用defaultdict
在首次访问时生成数字,并与计数器结合使用:
from collections import defaultdict
from itertools import count
from functools import partial
label_to_number = defaultdict(partial(next, count(1)))
[(label_to_number[label], label) for label in labels]
这将按照labels
中首次出现的标签的顺序生成计数。
演示:
>>> labels = ["brown", "black", "blue", "brown", "brown", "black"]
>>> label_to_number = defaultdict(partial(next, count(1)))
>>> [(label_to_number[label], label) for label in labels]
[(1, 'brown'), (2, 'black'), (3, 'blue'), (1, 'brown'), (1, 'brown'), (2, 'black')]
因为我们使用字典,所以标签到数字的查找是固定成本的,因此整个操作将根据labels
列表的长度采用线性时间。
或者,使用set()
获取唯一值,然后将这些值映射到enumerate()
计数:
label_to_number = {label: i for i, label in enumerate(set(labels), 1)}
[(label_to_number[label], label) for label in labels]
这更加随意地分配数字,因为set()
个对象没有被排序:
>>> label_to_number = {label: i for i, label in enumerate(set(labels), 1)}
>>> [(label_to_number[label], label) for label in labels]
[(2, 'brown'), (3, 'black'), (1, 'blue'), (2, 'brown'), (2, 'brown'), (3, 'black')]
这需要两次循环labels
。
这两种方法都不需要您首先定义标签字典;映射是自动创建的。
答案 1 :(得分:3)
您可以先创建一个字典:
dict = {"brown":1 , "black": 2, "blue": 3 }
然后:
li = ["brown", "black", "blue", "brown", "brown", "black"]
[dict[i] for i in li]
答案 2 :(得分:1)
试试这个:
lst = ["brown", "black", "blue", "brown", "brown", "black"]
d = {"brown":1, "black":2, "blue":3}
[d[k] for k in lst]
=> [1, 2, 3, 1, 1, 2]
当然,要实现这一点,你必须在某处定义等价 - 上面,我使用了字典。否则,无法知道棕色对应于数字1等等。
答案 3 :(得分:0)
再现您要求的答案的最简单的代码是:
l = ["brown", "black", "blue", "brown", "brown", "black"]
i = [l.index(x)+1 for x in l]
print i
>>> [1, 2, 3, 1, 1, 2]
对于一个长长的清单,这可能会变得很慢,但它会产生你所要求的,没有任何准备。