Won*_*hin 6 python lambda dictionary list nested-lists
输入
我有一个非常复杂的清单。
total_aug_rule_path_list =
[[[[['#1_0_0', '#2_0_0', '#3_0_0'], ['#1_0_1', '#2_0_1', '#3_0_1']],
[['#1_0_0', '#2_0_0', '#3_0_0'], ['#1_0_1', '#2_0_1', '#3_0_1']]],
[[['#1_1_0', '#2_1_0', '#3_1_0', '#4_1_0'],
['#1_1_1', '#2_1_1', '#3_1_1', '#4_1_1']]]]]
Run Code Online (Sandbox Code Playgroud)
我有一本字典,其中列表的每个元素作为键。
sym2id_dict = {
'#1_0_0': 1,
'#1_0_1': 2,
'#1_1_0': 3,
'#1_1_1': 4,
'#2_0_0': 5,
'#2_0_1': 6,
'#2_1_0': 7,
'#2_1_1': 8,
'#3_0_0': 9,
'#3_0_1': 10,
'#3_1_0': 11,
'#3_1_1': 12,
'#4_1_0': 13,
'#4_1_1': 14,}
Run Code Online (Sandbox Code Playgroud)
我将把列表的每个元素映射到字典的值。
输出
[[[[[1, 5, 9], [2, 6, 10]], [[1, 5, 9], [2, 6, 10]]],
[[[3, 7, 11, 13], [4, 8, 12, 14]]]]]
Run Code Online (Sandbox Code Playgroud)
我尝试了以下方法来尽可能少地使用 for 循环。
list(map(lambda proofpaths_to_goal :
list(map(lambda proofpaths_to_template :
list(map(lambda proofpath :
list(map(lambda single_augment : list(map(lambda x : sym2id_dict[x], single_augment)),
proofpath)), proofpaths_to_template)), proofpaths_to_goal)),total_aug_rule_path_list))
Run Code Online (Sandbox Code Playgroud)
如果您能让我知道是否有一种比此方法更容易或更易读的方法,我将不胜感激。
Bla*_*ven 11
您可以将列表转换为字符串文字,并使用正则表达式替换字典中的相应字符串,然后将字符串文字转换回列表。
import re
import ast
s = str(total_aug_rule_path_list) #converts to string literal
for element in re.findall(r'#\d_\d_\d', s):
s = s.replace(element, str(sym2id_dict[element]))
s = s.replace("'", "") #because each integer is a string
s = ast.literal_eval(s) #converts string literal back to list, do NOT use eval(s)
print(s)
Run Code Online (Sandbox Code Playgroud)
编辑:请注意,在任何语言(python、perl、js 等)中使用它都是危险的eval()
,因为它可能导致代码注入错误。为了安全起见,请使用ast.literal_eval()
.
输出
[[[[[1, 5, 9], [2, 6, 10]], [[1, 5, 9], [2, 6, 10]]],
[[[3, 7, 11, 13], [4, 8, 12, 14]]]]]
Run Code Online (Sandbox Code Playgroud)
以下是一些替代方案:
[[[[[sym2id_dict[l4] for l4 in l3] for l3 in l2] for l2 in l1] for l1 in l0] for l0 in total_aug_rule_path_list]
Run Code Online (Sandbox Code Playgroud)
尽管这可能并不容易阅读。
此方法不适用于您的示例列表,因为 numpy 数组不能是参差不齐的数组(即所有同等嵌套的列表必须具有相同的长度)。但是,当您不使用不规则数组时,您可以执行以下操作:
import numpy as np
total_aug_rule_path_list = [[
[[['#1_0_0', '#2_0_0', '#3_0_0'], ['#1_0_1', '#2_0_1', '#3_0_1']]],
[[['#1_1_0', '#2_1_0', '#3_1_0'], ['#1_1_1', '#2_1_1', '#3_1_1']]]
]]
sym2id_dict = {...} # your dict here
total_aug_rule_path_list_array = np.array(total_aug_rule_path_list)
print(np.vectorize(sym2id_dict.get)(total_aug_rule_path_list_array))
Run Code Online (Sandbox Code Playgroud)
这将该sym2id_dict.get
函数应用于数组中的每个字符串。sym2id_dict._getitem__
如果您希望当键不在字典中时抛出错误,您可以将其更改为。
此函数会递归,直到输入不是列表为止。这适用于像[1, [2, 3]]
. 如果您希望它适用于列表以外的其他内容,请参阅此处。
def vectorised_apply(f, values):
if isinstance(values,list):
return [vectorised_apply(f,value) for value in values]
else:
return f(values)
print(vectorised_apply(sym2id_dict.get, total_aug_rule_path_list))
Run Code Online (Sandbox Code Playgroud)
这种变化递归到固定深度,因此不需要isinstance
检查:
def vectorised_apply_n(f, values, n=0):
if n == 0:
return f(values)
else:
return [vectorised_apply_n(f, value, n=n-1) for value in values]
print(vectorised_apply_n(sym2id_dict.get, total_aug_rule_path_list, 5))
Run Code Online (Sandbox Code Playgroud)
如果你真的想要,你可以使用一个技巧来itertools.accumulate
将这个固定的递归深度函数变成一个单一的表达式,但它非常不Pythonic并且很难理解。
from itertools import accumulate
print(
list(accumulate(
range(5), # do 5 times because the list is nested 5 times
initial=lambda x: sym2id_dict[x], # base case: lookup in the dictionary
func=lambda rec, _: lambda xs: [rec(x) for x in xs] # recursive case: build a bigger function using a previous function `rec`
))[-1](total_aug_rule_path_list)) # get the last function from the list
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
119 次 |
最近记录: |