假设我有一个列表
A = ['A', 'A', 'A', 'B', 'B', 'C']
如何将其转为
B = [0, 0, 0, 1, 1, 2]
我是这样写的
C = {t[1]:t[0] for t in enumerate(list(set(A)))}
B = [C[e] for e in A]
它给了
[1, 1, 1, 2, 2, 0]
即。订单看起来是随机的,整个代码也很复杂。
有没有更简单的方法?
答案 0 :(得分:1)
您可以尝试讨厌的(虽然比当前代码更容易理解),例如:
>>> B = [ord(x) - 65 for x in A]
>>> B
[0, 0, 0, 1, 1, 2]
如果A是一个大清单,请考虑让B成为生成器,如下所示:
B = (ord(x) - 65 for x in A)
答案 1 :(得分:1)
a = ['A', 'A', 'A', 'B', 'B', 'C']
x = sorted(set(a))
b = [x.index(y) for y in a]
print(b)
[0, 0, 0, 1, 1, 2]
答案 2 :(得分:1)
您是否希望订单由唯一元素的字母顺序或它们首次出现在原始列表中的顺序决定?例如,应该[' C',' A',' A',' A',' B', ' B',' C']变成[2,0,0,0,1,1,2]或[0,1,1,1,2,2, 0]如果是前者:
uniques = list(set(A))
uniques.sort()
uniques_dict = {uniques[i]:i for i in range(len(uniques))}
B = [uniques_dict[a] for a in A]
对于后者:
uniques_dict = {}
ordinal = 0
for a in A:
if not (a in uniques_dict.keys):
uniques_dict[a] = ordinal
ordinal = ordinal+1
B = [uniques_dict[a] for a in A]
答案 3 :(得分:0)
似乎构建字典/映射是关键,使用它只是主题的变体。甚至构建字典也将是主题的变体 - 在读者眼中是否更好/更差/更简单/更复杂。
>>> import itertools
>>> ordinatates = itertools.count(0)
>>> a = ['a', 'b', 'c', 'a', 'a', 'c', 'c']
>>> unique = sorted(set(a))
>>> d = {thing:ordinal for thing, ordinal in zip(unique, ordinates)}
应用
>>> list(map(d.get, a))
[0, 1, 2, 0, 0, 2, 2]
>>>
如果a
中的项目不在d
中,则会抛出KeyException。
>>> import operator
>>> a = ['a','b','c', 'a', 'a', 'c','c']
>>> m = map(operator.itemgetter, a)
>>> [get(d) for get in m]
[0, 1, 2, 0, 0, 2, 2]
>>>
类似,没有警告
class Foo(dict):
def __call__(self, item):
'''Returns self[item] or None.'''
try:
return self[item]
except KeyError as e:
# print or log something descriptive - print(repr(e))
return None
>>> ordinates = itertools.count(0)
>>> a = ['a','b','c', 'a', 'a', 'c','c']
>>> unique = sorted(set(a))
>>> d = Foo((thing,ordinal) for thing, ordinal in zip(unique, ordinates))
>>> result = list(map(d, a))
>>> result
[0, 1, 2, 0, 0, 2, 2]
>>>
所有假设你想要排序项的序数位置 - 因为你的示例列表很方便 pre -sorted。如果您在列表中查找首次出现唯一事物的位置,请构建如下映射:
import itertools
ordinal = itertools.count()
b = ['c','b','c', 'a', 'a', 'c','c']
d = {}
for thing in b:
if thing in d:
continue
d[thing] = next(ordinal)
应用
>>> list(map(d.get, b))
[0, 1, 0, 2, 2, 0, 0]
>>>
@Abdou在他的评论中暗示了这一点,但你没方便回答。
如果你有一个可以写成
的单行迷信d = {}
d.update((thing,d[thing] if thing in d else next(ordinal)) for thing in b)
答案 4 :(得分:0)
我将假设:1。你不依赖于作为字母的元素; 2.你想根据列表A
中的第一个外观来索引它们。
>>> A = ['A', 'A', 'A', 'B', 'B', 'C']
>>> seen=set()
>>> C={x:len(seen)-1 for x in A if not (x in seen or seen.add(x))}
>>> C
{'B': 1, 'C': 2, 'A': 0}
>>> list(map(C.get, A))
[0, 0, 0, 1, 1, 2]
第二行定义了一个集合seen
,它将存储我们已经在下一行的列表理解中看到的A
元素。
第三行定义了将唯一元素映射到其索引的dictioanry。这有点棘手(尽管不是那么不寻常)。
我们遍历A
。
案例1:看到值x
,因此x in seen or ...
为True
,第二部分未评估,not(...)
返回{{1} }}:False
被忽略。
案例2:看到x
值不,因此x
为x in seen
,第二部分进行评估。提醒False
将始终返回seen.add
,在此上下文中相当于None
。 False
为x in seen or seen.add(x)
,但False
已添加到x
。并且seen
返回not(...)
:True
映射到x
的len,每个新元素的增量为1.
第六行只是将新定义的字典映射到seen
的值。