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

More elegant list comprehension using another enumerated list as a key

我有一个列表列表:

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

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

>>> key = list(enumerate(["A","B","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,1,0]]

但是,我似乎无法弄清楚如何在没有 for 循环的情况下使用单个列表理解来获取结果。关于我将如何做到这一点有什么想法吗?

如果我没理解错的话,你想将 for-loop 转换为列表理解。您可以创建一个映射(在您的问题中,这是倒置的 key dictionary`),然后使用列表理解:

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

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

打印:

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

编辑:感谢@kaya3,仅枚举的较轻版本:

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

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

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

from collections import defaultdict

d = defaultdict(lambda: len(d))

array = [["A", "B", "C"], ["C", "B", "A"]]
array = [[d[x] for x in sub] for sub in array]
# [[0, 1, 2], [2, 1, 0]]

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

array = [["A","B","C"],["C","B","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, 1, 2], [2, 1, 0]]

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

letters = ['A', 'B', 'C']
array = [['A', 'B', 'C'], ['C', 'B', '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', 'B', 'C']
array = [['A', 'B', 'C'], ['C', 'B', 'A']]
array = [list(map(letters.index, row)) for row in array]