#python-3.x #collections
#python-3.x #Коллекции
Вопрос:
У меня есть вложенный словарь со структурой ниже. Как и ключ values
, может быть несколько ключей, например values1
, values2
. Я ищу random1
и random2
строки. Если существует, то нужно проверить val
, существует или нет.
d = {"values": [
{
"name": "A1234",
"description": "A1234-Description ",
"random1": {
"abcd": {
"val": 1
}
},
"random2": {
"abcd": {
"val": -1
}
}
},
{
"name": "A4567",
"description": "A4567-Description ",
"random1": {
"abcd": {
"val": 1
}
},
"random2": {
"abcd": {
"val": -1
}
}
},
{
"name": "B1234",
"description": "B1234-Description ",
}
]}
Код:
for i in d["values"]:
for k, v in i.items():
if k in ("random1", "random2") and "abcd" in v1:
if len(v1["abcd"]) != 0:
if "val" in v1["abcd"]:
print("Found")
else:
print("Not found")
else:
print("empty")
Я считаю, что нет ярлыка для перехода к словарю. Но, безусловно, для этого должны быть некоторые методы / оптимизация (сокращение количества циклов for / if)
Может кто-нибудь, пожалуйста, подсказать мне, можно ли это сделать с помощью коллекций и т. Д
Комментарии:
1. Каков ваш желаемый результат? A
Found, Not Found, empty
для каждогоrandonm[12] -> abcd
?2. @schwobaseggl: для каждого random1 или random2 ‘val’ найден или не найден.
Ответ №1:
Вам нужен рекурсивный алгоритм, чтобы пройти через древовидность словаря
def recursive_iter(obj, keys=()):
if isinstance(obj, dict):
for k, v in obj.items():
yield from recursive_iter(v, keys (k,))
elif any(isinstance(obj, t) for t in (list, tuple)):
for idx, item in enumerate(obj):
yield from recursive_iter(item, keys (idx,))
else:
yield keys, obj
Здесь вы можете распечатать результат
for keys, item in recursive_iter(d):
print(keys, ' -> ', item)
Который отображает :
('values', 0, 'name') -> A1234
('values', 0, 'description') -> A1234-Description
('values', 0, 'random1', 'abcd', 'val') -> 1
('values', 0, 'random2', 'abcd', 'val') -> -1
('values', 1, 'name') -> A4567
('values', 1, 'description') -> A4567-Description
('values', 1, 'random1', 'abcd', 'val') -> 1
('values', 1, 'random2', 'abcd', 'val') -> -1
('values', 2, 'name') -> B1234
('values', 2, 'description') -> B1234-Description
Редактировать:
for keys, item in recursive_iter(d):
if "val" in keys and "abcd" in keys:
print("FOUNDn", keys, ' -> ', item)
elif "val" not in keys and "abcd" in keys:
print("NOT FOUNDn", keys, ' -> ', item)
Комментарии:
1. мы должны убедиться, что «val» означает «abcd» для ‘random1’ или ‘random2’ или обоих.
2. почему эта проверка item == 1 и item == -1 ?
3. независимо от того, val = 1 или -1, просто чтобы проверить, существует ли «val» для «abcd» ‘random1’ или ‘random2’ или обоих
4. Если в порядке словаря, если что-либо, кроме ‘random1’ и ‘random2’ в d [«values»] [index].keys(), не должно беспокоить. Следует учитывать, если это только ‘random1’ ‘random2’
5.Я отредактировал. На самом деле, поскольку ваш запрос не касается рекурсивного исследования, и если ваш словарь всегда в этом формате, ваш скрипт уже хорош. Вы можете пропустить второй
for
цикл и включить в свойif
оператор :if 'random1' in i and 'abcd' in i['random1']:
if 'random2' in i and 'abcd' in i['random2']:
if 'random1' not in i and 'random2' not in i: