使用另一个枚举列表作为键可以更优雅地理解列表

问题描述

我有一个列表列表:

>>> array = [["A","B","C"],["C","A"]]

我还有一个用于枚举的密钥:

>>> key = list(enumerate(["A","C"]))
>>> print (key)
[(0,"A"),(1,"B"),(2,"C")]

我想使用列表推导根据键将数组中的字符串转换为数字。我做了以下工作,就能得到想要的结果:

>>> for i in key:
...    board = [[i[0] if x in i else x for x in y] for y in board] 
>>> print(board)
[[0,1,2],[2,0]]

但是,我似乎无法弄清楚如何在没有for循环的情况下使用单个列表推导来获得结果。关于如何执行此操作的任何想法?

解决方法

如果我对您的理解正确,则希望将for-loop转换为列表理解。您可以创建一个映射的(在您的问题中,这是倒置的key字典`),然后使用列表理解:

array = [["A","B","C"],["C","A"]]
mapper = {v:k for k,v in dict(enumerate(["A","C"])).items()}

print( [[mapper[v] for v in subl] for subl in array] )

打印:

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

编辑:感谢@ kaya3,仅列举一个较轻的版本:

array = [["A",v in enumerate(["A","C"])}

print( [[mapper[v] for v in subl] for subl in array] )
,

您可以使用defaultdict长度技巧在单个迭代中按出现的顺序获得唯一的整数表示形式:

from collections import defaultdict

d = defaultdict(lambda: len(d))

array = [["A","A"]]
array = [[d[x] for x in sub] for sub in array]
# [[0,0]]
,

使用python 3.8,您可以在一行中使用与@AndrejKesely相同的方法,通过列表理解内的walrus-operator创建mapper

array = [["A","A"]]

arr2 = [[ mapper[p] for p in l] for l in array 
        if (mapper := {v:k for k,v in enumerate(array[0])})] 

print(arr2)

输出:

[[0,0]]
,

您可以将key做成字典,将字母映射到它们的索引,然后进行映射:

letters = ['A','B','C']
array = [['A','C'],['C','A']]
key = {x: i for i,x in enumerate(letters)}
array = [list(map(key.get,row)) for row in array]

或者,由于letters很短,letters.index的效率足够高,以至于构建密钥根本没有多大意义:

letters = ['A','A']]
array = [list(map(letters.index,row)) for row in array]