return 嵌套字典中所有列表中第 n 个值的字典并保留其他值
return dictionary with nth value in all lists within a nested dictionary and retain other values
我有一本看起来像这样的字典:
dict_in = {'key0': {a: [A, B, C], b: [A, B, C]}, 'key1': {c: [A, B, C], d: [A, B, C]}, 'key2': {e: 0, f: 0}}
我想要一个 returns 相同字典但没有列表的函数(或其他函数)。代替列表的是一个值,它对应于每个列表中的第 n 个值。对于没有相应列表的键,我只希望值保持不变。例如,一些函数是这样的:
nth_val = 2
def take_nth_value_from_lists_in_nested_dict(list_in, nth_val):
...things and stuff...
return dict_out
dict_out = {'key0': {a: B, b: B}, 'key1': {c: B, d: B}, 'key2': {e: 0, f: 0}}
请注意 key2 是如何保持不变的。我不知道如何优雅地做到这一点,所以任何帮助将不胜感激!
你可以试试:
list_in = {'key0': {'a': ['A', 'B', 'C'], 'b': ['A', 'B', 'C']}, 'key1': {'c': ['A', 'B', 'C'], 'd': ['A', 'B', 'C']}, 'key2': {'e': 0, 'f': 0}}
nth = 1
for k,v in list_in.items():
for k2 in v.keys():
element = list_in[k][k2]
if isinstance(element, list):
list_in[k][k2] = element[nth]
print(list_in)
它returns:
{'key0': {'a': 'B', 'b': 'B'},
'key1': {'c': 'B', 'd': 'B'},
'key2': {'e': 0, 'f': 0}}
我会用递归来做:
def take_nth_value_from_lists_in_nested_dict(obj, n: int):
if isinstance(obj, dict):
return {k: take_nth_value_from_lists_in_nested_dict(v, n) for k, v in obj.items()}
if isinstance(obj, list):
return take_nth_value_from_lists_in_nested_dict(obj[n-1], n)
return obj
>>> take_nth_value_from_lists_in_nested_dict({'a': ['A', 'B', 'C'], 'b': ['A', 'B', 'C'], 'key1': {'c': ['A', 'B', 'C'], 'd': ['A', 'B', 'C']}, 'key2': {'e': 0, 'f': 0}}, 2)
{'a': 'B', 'b': 'B', 'key1': {'c': 'B', 'd': 'B'}, 'key2': {'e': 0, 'f': 0}}
这应该适用于任意深度的嵌套,包括在列表元素内(例如,如果第 N 个列表元素本身是一个包含更多 dicts/lists 的字典)。
单线解决方案可能如下所示:
list_in = {'key0': {'a': ['A', 'B', 'C'], 'b': ['A', 'B', 'C']}, 'key1': {'c': ['A', 'B', 'C'], 'd': ['A', 'B', 'C']}, 'key2': {'e': 0, 'f': 0}}
nth = 1
list_out = {k: {k2: v2 if not isinstance(v2,list) else v2[nth] \
for k2,v2 in v.items() } \
for k,v in list_in.items() }
print list_out
{'key2': {'e': 0, 'f': 0}, 'key1': {'c': 'B', 'd': 'B'}, 'key0': {'a': 'B', 'b': 'B'}}
请注意,我用字符串替换了键和列表的值。
我对你的理解是正确的,你想读出嵌套字典中列表的第 n 个元素,因此需要一个函数来执行此操作。
我解决这个任务的方法是递归的,但在我们深入研究函数的工作方式之前,让我们首先尝试了解我们可以用字典做什么。以下是使用字典时的四种有用方法:
.keys()
.values()
.items()
.update()
test_dict = {'a':1, 'b':2, 'c':3}
# Read out keys
list(test_dict.keys())
>>> ['a', 'b', 'c']
# Read out values
list(test_dict.values())
>>> [1, 2, 3]
# Read out keys and values together
list(test_dict.items())
>>> [('a', 1), ('b', 2), ('c', 3)]
# Update a dictionary with a new key, value pair or overwrite an existing one
test_dict.update({'d':4})
test_dict
>>> {'a': 1, 'b': 2, 'c': 3, 'd': 4}
注意我们用方法 .items():
得到了什么
以键值对作为元组的列表
# I'm a tuple
('something','something else','etc.')
我们可以利用 属性 列表可以用 for 循环迭代,这正是我们在函数开头所需要的。那么让我们开始编码吧:
def nth_element_from_list_in_nested_dict(nested_dict, list_index):
# Iterate trough a list with tuples
for key,val in nested_dict.items():
变量 key、val 现在代表各个元组的条目:
根据我们的 test_dict 这将是:
# On the first iteration
key='a'
val=1
# On the second iteration
key='b'
val=2
# and so on...
由于我们假设传递给函数的字典是嵌套的,因此我们要检查变量 val 是否是另一个字典。这可以在 if 语句中完成:
def nth_element_from_list_in_nested_dict(nested_dict, list_index):
# Iterate trough a list with tuples
for key,val in nested_dict.items():
# Check if variable val is another dictionary
if isinstance(val, dict):
# isinstance(val, type: for example dict or list) returns True if val is of specified type
现在是函数的递归部分。只要传递给函数的字典的值是另一个字典,我们就会在函数内再次调用函数,直到值是另一种类型(比如列表!)。因为当我们有一个列表作为值时,我们不需要更深入地挖掘,因为我们已经达到了可以 select 第 n 个元素的值。希望这仍然有意义......让我们继续使用代码:
def nth_element_from_list_in_nested_dict(nested_dict, list_index):
# Iterate trough a list with tuples
for key,val in nested_dict.items():
# Check if variable val is another dictionary
if isinstance(val, dict):
nth_element_from_list_in_nested_dict(val, list_index) # calls the function again when val is another dictionary
elif isinstance(val, list):
当我们找到一个列表值时,我们现在可以用该列表中的第 n 个元素更新这个字典:
def nth_element_from_list_in_nested_dict(nested_dict, list_index):
# Iterate trough a list with tuples
for key,val in nested_dict.items():
# Check if variable val is another dictionary
if isinstance(val, dict):
nth_element_from_list_in_nested_dict(val, list_index) # calls the function again when val is another dictionary
elif isinstance(val, list):
nested_dict.update({key:val[list_index]}) # updates dictionary with the n-th element from val (when val is of type list)
我们现在要做的就是返回更新后的字典,看看函数是否真的按照您的示例字典的预期进行(我已经在 list_in[= 中替换了您的变量51=] 带有字符串,因为它们尚未定义)
### Input ###
list_in = {'key0':
{'a': ['A','B', 'C'],
'b': ['A', 'B', 'C']
},
'key1':
{'c': ['A', 'B', 'C'],
'd': ['A', 'B', 'C']
},
'key2': {
'e': 0,
'f': 0,
}
}
### Function ###
def nth_element_from_list_in_nested_dict(nested_dict, list_index):
#
for key,val in nested_dict.items():
if isinstance(val, dict):
nth_element_from_list_in_nested_dict(val, list_index)
elif isinstance(val, list):
nested_dict.update({key:val[list_index]})
return nested_dict
### Tests ###
# replace with first element (list_index=0)
to_be_updated = list_in.copy()
nth_element_from_list_in_nested_dict(to_be_updated, 0)
>>> {'key0': {'a': 'A', 'b': 'A'},
'key1': {'c': 'A', 'd': 'A'},
'key2': {'e': 0, 'f': 0}}
# replace with third element (list_index=2)
to_be_updated = list_in.copy()
nth_element_from_list_in_nested_dict(to_be_updated, 2)
>>> {'key0': {'a': 'C', 'b': 'C'},
'key1': {'c': 'C', 'd': 'C'},
'key2': {'e': 0, 'f': 0}}
原来是一个很长的解释,也许有些部分(比如函数中的递归部分)很难理解。此外,当列表长度不同时,此函数容易出错。
尽管如此,我希望这可以帮助您和其他人取得进步;)
我有一本看起来像这样的字典:
dict_in = {'key0': {a: [A, B, C], b: [A, B, C]}, 'key1': {c: [A, B, C], d: [A, B, C]}, 'key2': {e: 0, f: 0}}
我想要一个 returns 相同字典但没有列表的函数(或其他函数)。代替列表的是一个值,它对应于每个列表中的第 n 个值。对于没有相应列表的键,我只希望值保持不变。例如,一些函数是这样的:
nth_val = 2
def take_nth_value_from_lists_in_nested_dict(list_in, nth_val):
...things and stuff...
return dict_out
dict_out = {'key0': {a: B, b: B}, 'key1': {c: B, d: B}, 'key2': {e: 0, f: 0}}
请注意 key2 是如何保持不变的。我不知道如何优雅地做到这一点,所以任何帮助将不胜感激!
你可以试试:
list_in = {'key0': {'a': ['A', 'B', 'C'], 'b': ['A', 'B', 'C']}, 'key1': {'c': ['A', 'B', 'C'], 'd': ['A', 'B', 'C']}, 'key2': {'e': 0, 'f': 0}}
nth = 1
for k,v in list_in.items():
for k2 in v.keys():
element = list_in[k][k2]
if isinstance(element, list):
list_in[k][k2] = element[nth]
print(list_in)
它returns:
{'key0': {'a': 'B', 'b': 'B'},
'key1': {'c': 'B', 'd': 'B'},
'key2': {'e': 0, 'f': 0}}
我会用递归来做:
def take_nth_value_from_lists_in_nested_dict(obj, n: int):
if isinstance(obj, dict):
return {k: take_nth_value_from_lists_in_nested_dict(v, n) for k, v in obj.items()}
if isinstance(obj, list):
return take_nth_value_from_lists_in_nested_dict(obj[n-1], n)
return obj
>>> take_nth_value_from_lists_in_nested_dict({'a': ['A', 'B', 'C'], 'b': ['A', 'B', 'C'], 'key1': {'c': ['A', 'B', 'C'], 'd': ['A', 'B', 'C']}, 'key2': {'e': 0, 'f': 0}}, 2)
{'a': 'B', 'b': 'B', 'key1': {'c': 'B', 'd': 'B'}, 'key2': {'e': 0, 'f': 0}}
这应该适用于任意深度的嵌套,包括在列表元素内(例如,如果第 N 个列表元素本身是一个包含更多 dicts/lists 的字典)。
单线解决方案可能如下所示:
list_in = {'key0': {'a': ['A', 'B', 'C'], 'b': ['A', 'B', 'C']}, 'key1': {'c': ['A', 'B', 'C'], 'd': ['A', 'B', 'C']}, 'key2': {'e': 0, 'f': 0}}
nth = 1
list_out = {k: {k2: v2 if not isinstance(v2,list) else v2[nth] \
for k2,v2 in v.items() } \
for k,v in list_in.items() }
print list_out
{'key2': {'e': 0, 'f': 0}, 'key1': {'c': 'B', 'd': 'B'}, 'key0': {'a': 'B', 'b': 'B'}}
请注意,我用字符串替换了键和列表的值。
我对你的理解是正确的,你想读出嵌套字典中列表的第 n 个元素,因此需要一个函数来执行此操作。
我解决这个任务的方法是递归的,但在我们深入研究函数的工作方式之前,让我们首先尝试了解我们可以用字典做什么。以下是使用字典时的四种有用方法:
.keys()
.values()
.items()
.update()
test_dict = {'a':1, 'b':2, 'c':3}
# Read out keys
list(test_dict.keys())
>>> ['a', 'b', 'c']
# Read out values
list(test_dict.values())
>>> [1, 2, 3]
# Read out keys and values together
list(test_dict.items())
>>> [('a', 1), ('b', 2), ('c', 3)]
# Update a dictionary with a new key, value pair or overwrite an existing one
test_dict.update({'d':4})
test_dict
>>> {'a': 1, 'b': 2, 'c': 3, 'd': 4}
注意我们用方法 .items():
得到了什么
以键值对作为元组的列表
# I'm a tuple
('something','something else','etc.')
我们可以利用 属性 列表可以用 for 循环迭代,这正是我们在函数开头所需要的。那么让我们开始编码吧:
def nth_element_from_list_in_nested_dict(nested_dict, list_index):
# Iterate trough a list with tuples
for key,val in nested_dict.items():
变量 key、val 现在代表各个元组的条目:
根据我们的 test_dict 这将是:
# On the first iteration
key='a'
val=1
# On the second iteration
key='b'
val=2
# and so on...
由于我们假设传递给函数的字典是嵌套的,因此我们要检查变量 val 是否是另一个字典。这可以在 if 语句中完成:
def nth_element_from_list_in_nested_dict(nested_dict, list_index):
# Iterate trough a list with tuples
for key,val in nested_dict.items():
# Check if variable val is another dictionary
if isinstance(val, dict):
# isinstance(val, type: for example dict or list) returns True if val is of specified type
现在是函数的递归部分。只要传递给函数的字典的值是另一个字典,我们就会在函数内再次调用函数,直到值是另一种类型(比如列表!)。因为当我们有一个列表作为值时,我们不需要更深入地挖掘,因为我们已经达到了可以 select 第 n 个元素的值。希望这仍然有意义......让我们继续使用代码:
def nth_element_from_list_in_nested_dict(nested_dict, list_index):
# Iterate trough a list with tuples
for key,val in nested_dict.items():
# Check if variable val is another dictionary
if isinstance(val, dict):
nth_element_from_list_in_nested_dict(val, list_index) # calls the function again when val is another dictionary
elif isinstance(val, list):
当我们找到一个列表值时,我们现在可以用该列表中的第 n 个元素更新这个字典:
def nth_element_from_list_in_nested_dict(nested_dict, list_index):
# Iterate trough a list with tuples
for key,val in nested_dict.items():
# Check if variable val is another dictionary
if isinstance(val, dict):
nth_element_from_list_in_nested_dict(val, list_index) # calls the function again when val is another dictionary
elif isinstance(val, list):
nested_dict.update({key:val[list_index]}) # updates dictionary with the n-th element from val (when val is of type list)
我们现在要做的就是返回更新后的字典,看看函数是否真的按照您的示例字典的预期进行(我已经在 list_in[= 中替换了您的变量51=] 带有字符串,因为它们尚未定义)
### Input ###
list_in = {'key0':
{'a': ['A','B', 'C'],
'b': ['A', 'B', 'C']
},
'key1':
{'c': ['A', 'B', 'C'],
'd': ['A', 'B', 'C']
},
'key2': {
'e': 0,
'f': 0,
}
}
### Function ###
def nth_element_from_list_in_nested_dict(nested_dict, list_index):
#
for key,val in nested_dict.items():
if isinstance(val, dict):
nth_element_from_list_in_nested_dict(val, list_index)
elif isinstance(val, list):
nested_dict.update({key:val[list_index]})
return nested_dict
### Tests ###
# replace with first element (list_index=0)
to_be_updated = list_in.copy()
nth_element_from_list_in_nested_dict(to_be_updated, 0)
>>> {'key0': {'a': 'A', 'b': 'A'},
'key1': {'c': 'A', 'd': 'A'},
'key2': {'e': 0, 'f': 0}}
# replace with third element (list_index=2)
to_be_updated = list_in.copy()
nth_element_from_list_in_nested_dict(to_be_updated, 2)
>>> {'key0': {'a': 'C', 'b': 'C'},
'key1': {'c': 'C', 'd': 'C'},
'key2': {'e': 0, 'f': 0}}
原来是一个很长的解释,也许有些部分(比如函数中的递归部分)很难理解。此外,当列表长度不同时,此函数容易出错。 尽管如此,我希望这可以帮助您和其他人取得进步;)