我有一个字符串列表.我想为每个字符串分配一个唯一的编号(确切的数字并不重要),并按顺序使用这些编号创建一个相同长度的列表.以下是我最好的尝试,但我不满意有两个原因:
它假设相同的值彼此相邻
我必须用a开始列表0
,否则输出将是不正确的
我的代码:
names = ['ll', 'll', 'll', 'hl', 'hl', 'hl', 'LL', 'LL', 'LL', 'HL', 'HL', 'HL']
numbers = [0]
num = 0
for item in range(len(names)):
if item == len(names) - 1:
break
elif names[item] == names[item+1]:
numbers.append(num)
else:
num = num + 1
numbers.append(num)
print(numbers)
Run Code Online (Sandbox Code Playgroud)
我想使代码更通用,因此它将使用未知列表.有任何想法吗?
Cle*_*leb 17
如果不使用外部库(检查编辑的Pandas
解决方案),你可以如下做到这一点:
d = {ni: indi for indi, ni in enumerate(set(names))}
numbers = [d[ni] for ni in names]
Run Code Online (Sandbox Code Playgroud)
简要说明:
在第一行中,为列表中的每个唯一元素指定一个数字(存储在字典中d
;您可以使用字典理解轻松创建它; set
返回唯一元素names
).
然后,在第二行中,执行列表推导并将实际数字存储在列表中numbers
.
一个例子来说明它也适用于未排序的列表:
# 'll' appears all over the place
names = ['ll', 'll', 'hl', 'hl', 'hl', 'LL', 'LL', 'll', 'LL', 'HL', 'HL', 'HL', 'll']
Run Code Online (Sandbox Code Playgroud)
这是输出numbers
:
[1, 1, 3, 3, 3, 2, 2, 1, 2, 0, 0, 0, 1]
Run Code Online (Sandbox Code Playgroud)
如您所见,1
与之关联的数字ll
显示在正确的位置.
编辑
如果你有Pandas可用,你也可以使用pandas.factorize
(这对于大型列表来说似乎非常有效,并且对于这里解释的元组列表也可以正常工作):
import pandas as pd
pd.factorize(names)
Run Code Online (Sandbox Code Playgroud)
然后会回来
(array([(array([0, 0, 1, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0]),
array(['ll', 'hl', 'LL', 'HL'], dtype=object))
Run Code Online (Sandbox Code Playgroud)
因此,
numbers = pd.factorize(names)[0]
Run Code Online (Sandbox Code Playgroud)
如果条件是数字是唯一的并且确切的数字不重要,那么您可以构建一个映射,将列表中的每个项目动态地与唯一的数字相关联,从计数对象中分配值:
from itertools import count
names = ['ll', 'll', 'hl', 'hl', 'LL', 'LL', 'LL', 'HL', 'll']
d = {}
c = count()
numbers = [d.setdefault(i, next(c)) for i in names]
print(numbers)
# [0, 0, 2, 2, 4, 4, 4, 7, 0]
Run Code Online (Sandbox Code Playgroud)
您可以通过map
在列表和计数对象上使用并将地图函数设置为{}.setdefault
(请参阅@ StefanPochmann的注释)来取消额外的名称:
from itertools import count
names = ['ll', 'll', 'hl', 'hl', 'LL', 'LL', 'LL', 'HL', 'll']
numbers = map({}.setdefault, names, count()) # call list() on map for Py3
print(numbers)
# [0, 0, 2, 2, 4, 4, 4, 7, 0]
Run Code Online (Sandbox Code Playgroud)
作为额外的,你也可以使用np.unique
,以防你已经安装了numpy:
import numpy as np
_, numbers = np.unique(names, return_inverse=True)
print(numbers)
# [3 3 2 2 1 1 1 0 3]
Run Code Online (Sandbox Code Playgroud)
如果您有k
不同的值,则会按照首次出现的顺序将它们映射0
到整数:k-1
>>> names = ['b', 'c', 'd', 'c', 'b', 'a', 'b']
>>> tmp = {}
>>> [tmp.setdefault(name, len(tmp)) for name in names]
[0, 1, 2, 1, 0, 3, 0]
Run Code Online (Sandbox Code Playgroud)