Сообщить об ошибке.

Методы модификации и извлечения данных из словаря python-benedict

Материал представляет справочные данные по встроенным утилитам модуля python-benedict, предназначенным для модификации и извлечения данных по необходимости из словаря benedict.

Содержание:


Benedict.clean(strings=True, collections=True):

Метод Benedict.clean() очистит текущий экземпляр словаря benedict, удалив ключи верхнего уровня, имеющие пустые значения : None, '', {}, [], (). Если флаги strings или collections (dict, list, set, tuple) имеют значение False, то связанные пустые значения удалены не будут.

from benedict import benedict

data = {
    'name': 'Josh',
    'occupation': '',
    'awesome': None,
    'skills': {
        'prog': {
            'Python': '5 stars',
            'JavaScript': ''
        }
    }
}

d = benedict(data)
d.clean()
print(d.dump())
# {
#     "name": "Josh",
#     "skills": {
#         "prog": {
#             "JavaScript": "",
#             "Python": "5 stars"
#         }
#     }
# }

Benedict.clone():

Метод Benedict.clone() возвращает клон (глубокую копию) экземпляра словаря benedict.

from benedict import benedict
d = benedict(existing_dict)
c = d.clone()

Benedict.dump():

Метод Benedict.dump() возвращает удобочитаемое представление любого словаря/списка. Этот метод может использоваться как статический метод, так и метод экземпляра.

>>> from benedict import benedict
>>> d = benedict(existing_dict)
print(d.dump())
# или
>>> s = benedict.dump(d.keypaths())
>>> print(s)

Benedict.filter(predicate):

Метод Benedict.filter() возвращает отфильтрованный словарь по ключам верхнего уровня, используя функцию predicate. Функция predicate получает в качестве аргументов ключ и значение и должна возвращать логическое значение.

from benedict import benedict

data = {
    'name': 'Josh',
    'occupation': 'Data scientist',
    'awesome': '',
    'skills': {
        'prog': {
            'Python': '5 stars',
            'JavaScript': '4 stars'
        }
    }
}

d = benedict(data)
predicate = lambda k, v: v != ''
f = d.filter(predicate)
print(f.dump())
# {
#     "name": "Josh",
#     "skills": {
#         "prog": {
#             "JavaScript": "",
#             "Python": "5 stars"
#         }
#     }
# }

Benedict.find(keys, default=0):

Метод Benedict.find() возвращает первое совпадение при поиске заданных ключей/путей к ключам заданных в списке keys. Если результат не найден, то возвращается значение по умолчанию default.

from benedict import benedict

data = {
    'name': 'Josh',
    'occupation': 'Data scientist',
    'awesome': '',
    'skills': {
        'prog': {
            'Python': '5 stars',
            'JS': '4 stars'
        }
    }
}

d = benedict(data)
keys = ['skills.prog.Java', 'skills.prog.Python']
print(d.find(keys, default=0))
# '5 stars'

Benedict.flatten(separator="_"):

Метод Benedict.flatten() возвращает новый сглаженный словарь, используя разделитель separator, который используется для объединения вложенных ключей словаря.

from benedict import benedict

data = {
    'name': 'Josh',
    'occupation': 'Data scientist',
    'awesome': '',
    'skills': {
        'prog': {
            'Python': '5 stars',
            'JS': '4 stars'
        }
    }
}

d = benedict(data)
f = d.flatten(separator="_")
print(f.dump())
# {
#     "awesome": "",
#     "name": "Josh",
#     "occupation": "Data scientist",
#     "skills_prog_JS": "4 stars",
#     "skills_prog_Python": "5 stars"
# }

Benedict.unflatten(separator="_"):

Метод Benedict.unflatten() возвращает восстановленный словарь, разделенный на вложенные пути ключей, используя заданный разделитель.

from benedict import benedict

data = {
    'awesome': '',
    'name': 'Josh',
    'occupation': 'Data scientist',
    'skills_prog_JS': '4 stars',
    'skills_prog_Python': '5 stars'
}

d = benedict(data)
u = d.unflatten(separator="_")
print(u.dump())
# {
#     "awesome": "",
#     "name": "Josh",
#     "occupation": "Data scientist",
#     "skills": {
#         "prog": {
#             "JS": "4 stars",
#             "Python": "5 stars"
#         }
#     }
# }

Benedict.groupby(key, by_key):

Метод Benedict.groupby() возвращает новый словарь, cгруппированных по значению by_key. Словарь для группировки выбирается по ключу key из экземпляра словаря Benedict и должен представлять собой список словарей.

from benedict import benedict

data = {
    'students': [
        {'name': 'Alice', 'age': 20, 'major': 'Computer Science'},
        {'name': 'Bob', 'age': 21, 'major': 'Electrical Engineering'},
        {'name': 'Charlie', 'age': 19, 'major': 'Mathematics'},
        {'name': 'Josh', 'age': 24, 'major': 'Mathematics'},
        {'name': 'Lindsey', 'age': 24, 'major': 'Computer Science'},
        {'name': 'Steve', 'age': 42, 'major': 'Electrical Engineering'},
        {'name': 'Tina', 'age': 30, 'major': 'Computer Science'},
        {'name': 'Jack', 'age': 16, 'major': 'Mathematics'},
    ]
}

d = benedict(data)
g = d.groupby("students", by_key="major")
print(g.dump())
# {
#     "Computer Science": [
#         {
#             "age": 20,
#             "major": "Computer Science",
#             "name": "Alice"
#         },
#         {
#             "age": 24,
#             "major": "Computer Science",
#             "name": "Lindsey"
#         },
#         {
#             "age": 30,
#             "major": "Computer Science",
#             "name": "Tina"
#         }
#     ],
#     "Electrical Engineering": [
#         {
#             "age": 21,
#             "major": "Electrical Engineering",
#             "name": "Bob"
#         },
#         {
#             "age": 42,
#             "major": "Electrical Engineering",
#             "name": "Steve"
#         }
#     ],
#     "Mathematics": [
#         {
#             "age": 19,
#             "major": "Mathematics",
#             "name": "Charlie"
#         },
#         {
#             "age": 24,
#             "major": "Mathematics",
#             "name": "Josh"
#         },
#         {
#             "age": 16,
#             "major": "Mathematics",
#             "name": "Jack"
#         }
#     ]
# }

Benedict.invert(flat=False):

Метод Benedict.invert() возвращает перевернутый словарь benedict, в котором значения становятся ключами, а ключи становятся значениями.

Словарь может иметь несколько ключей с одинаковыми значениями, что бы исключить потерю данных, каждое значение будет иметь список ключей. Если flat равно True, то каждое значение будет иметь единственной значение ключа (используйте это поведение с осторожностью).

from benedict import benedict
data = {'a': 1, 'b': 2, 'c': 3, 'd': 3, 'e': 1}
d = benedict(data)
print(d.invert(flat=False))
# {1: ['a', 'e'], 2: ['b'], 3: ['c', 'd']}
print(d.invert(flat=True))
# {1: 'a', 2: 'b', 3: 'c'}

Benedict.items_sorted_by_keys(reverse=False):

Метод Benedict.items_sorted_by_keys() возвращает список кортежей элементов словаря (key, val), отсортированные по ключам верхнего уровня. Если значение reverse=True, список будет перевернут.

from benedict import benedict
data = {'a': 1, 'b': 2, 'c': 3, 'd': 3, 'e': 1}
d = benedict(data)
print(d.items_sorted_by_keys(reverse=False))
# [('a', 1), ('b', 2), ('c', 3), ('d', 3), ('e', 1)]

Benedict.items_sorted_by_values(reverse=False):

Метод Benedict.items_sorted_by_values() возвращает список кортежей элементов словаря (key, val), отсортированные по значениям ключей верхнего уровня.

Если значение reverse=True, список будет перевернут.

from benedict import benedict
data = {'a': 1, 'b': 2, 'c': 3, 'd': 3, 'e': 1}
d = benedict(existing_dict)
print(d.items_sorted_by_values(reverse=False))
# [('a', 1), ('e', 1), ('b', 2), ('c', 3), ('d', 3)]

Benedict.keypaths(indexes=False):

Метод Benedict.keypaths() возвращает список всех путей к ключам в словаре benedict. Если значение indexes=True, то выходные данные будут включать индексы значений списка.

from benedict import benedict

data = {
    'name': 'Josh',
    'skills': {
        'prog': {
            'Python': '5 stars',
            'JS': '4 stars'
        }
    }
}

d = benedict(data)
print(d.keypaths())
# ['name', 'skills', 'skills.prog', 'skills.prog.JS', 'skills.prog.Python']

Benedict.match(pattern, indexes=True):

Метод Benedict.match() возвращает список всех значений, путь к ключам которых соответствует заданному шаблону pattern (регулярному выражению или строке).

Если шаблон является строкой, то можно использовать подстановочный знак (например, [*] можно использовать для соответствия всем индексам списка). Если indexes=True, то шаблон будет сопоставляться также со значениями списка.

from benedict import benedict

data = {
    'students': [
        {'name': 'Alice', 'age': 20, 'major': 'Computer Science'},
        {'name': 'Bob', 'age': 21, 'major': 'Electrical Engineering'},
        {'name': 'Charlie', 'age': 19, 'major': 'Mathematics'},
        {'name': 'Josh', 'age': 24, 'major': 'Mathematics'},
        {'name': 'Lindsey', 'age': 24, 'major': 'Computer Science'},
        {'name': 'Steve', 'age': 42, 'major': 'Electrical Engineering'},
        {'name': 'Tina', 'age': 30, 'major': 'Computer Science'},
        {'name': 'Jack', 'age': 16, 'major': 'Mathematics'},
    ]
}

d = benedict(data)
# получим имя первого студента и специальность
print(d.match("students[0].(name|major)"))
# ['Computer Science, 'Alice']

# получим имена всех студентов
print(d.match("students[*].name"))
# ['Alice', 'Bob', 'Charlie', 'Josh', 'Lindsey', 'Steve', 'Tina', 'Zoe', 'Jack']

Benedict.merge(*dicts, overwrite=True, concat=False):

Метод Benedict.merge() объединяет один или несколько объектов словаря *dicts в текущий экземпляр dict. Ключи подсловарей будут объединены.

Если для аргумента overwrite установлено значение False, то существующие значения не будут перезаписаны. Если concat имеет значение True, то значения будут объединены в список.

from benedict import benedict
new_key = {'foo': [{'bar': {'test': 'update'}}]}

# overwrite=True
d = benedict({'foo': [{'bar': {'rer' : 'value'}}]})
d.merge(new_key, overwrite=True) 
print(d)
# {'foo': [{'bar': {'test': 'update'}}]}

# overwrite=False
d = benedict({'foo': [{'bar': {'rer' : 'value'}}]})
d.merge(new_key, overwrite=False) 
print(d)
# {'foo': [{'bar': {'rer' : 'value'}}]}

# concat=True
d = benedict({'foo': [{'bar': {'rer' : 'value'}}]})
d.merge(new_key, concat=True) 
print(d)
# {'foo': [{'bar': {'rer': 'value'}}, {'bar': {'test': 'update'}}]}

Benedict.move(key, new_key, overwrite=True):

Метод Benedict.move() перемещает элемент из key в new_key. Такое поведение можно использовать для переименования ключа.

from benedict import benedict
data = {'Python': '5 stars', 'JS': '4 stars'}
d = benedict(data)
d.move("Python", "Py")
print(d)
# {'JS': '4 stars', 'Py': '5 stars'}

Если new_key существует, то его значение будет перезаписано значением key.

d.move("Py", "JS")
print(d)
# {'JS': '5 stars'}

Benedict.remove(keys):

Метод Benedict.remove() удаляет несколько ключей keys из словаря benedict. Аргумент keys принимает один ключ или несколько в виде list или *args.

from benedict import benedict

data = {
    'name': 'Josh',
    'occupation': 'Data scientist',
    'skills': {
            'Python': '5 stars',
            'JavaScript': '4 stars'
    }
}

d = benedict(data)
d.remove(['name', 'skills.JavaScript'])
print(d.dump())
# {
#     "occupation": "Data scientist",
#     "skills": {
#         "Python": "5 stars"
#     }
# }

Benedict.rename(key, key_new):

Метод Benedict.rename() переименовывает ключ элемента словаря с 'key' на 'key_new'.

Если key_new существует, то будет выдано сообщение об ошибке KeyError.

from benedict import benedict
data = {'Python': '5 stars', 'JS': '4 stars'}
d = benedict(data)
d.rename("Python", "Py")
print(d)
# {'JS': '4 stars', 'Py': '5 stars'}

Benedict.search(query, in_keys=True, in_values=True, exact=False, case_sensitive=False):

Метод Benedict.search() ищет и возвращает список элементов (dict, key, value), соответствующих заданному запросу query.

Аргументы:

  • query: запрос на поиск;
  • in_keys=True: искать совпадения в ключах словаря;
  • in_values=True: искать совпадения в значениях словаря;
  • exact=False: отвечает за точность совладения. Если True, то полное совпадение с query. Если False, то частичное совпадение, например, ищет подстроку в строке.
  • case_sensitive=False: искать с учетом регистра или нет.
from benedict import benedict

data = {
    'name': 'Josh',
    'occupation': 'Data scientist programmer',
    'prog': {
            'Python': '5 stars',
            'JS': '4 stars'
    }
}

d = benedict(data)

# ищем подстроку 'prog'
lst = d.search('prog')
for _, key, val in lst:
    print(f"KEY: {key} => VAL: {val}")
# KEY: occupation => VAL: Data scientist programmer
# KEY: prog => VAL: {'Python': '5 stars', 'JS': '4 stars'}

Или еще один пример более практичный:

from benedict import benedict

data = {
    'students': [
        {'name': 'Alice', 'age': 20, 'major': 'Computer Science'},
        {'name': 'Bob', 'age': 21, 'major': 'Electrical Engineering'},
        {'name': 'Charlie', 'age': 19, 'major': 'Mathematics'},
        {'name': 'Josh', 'age': 24, 'major': 'Mathematics'},
        {'name': 'Lindsey', 'age': 24, 'major': 'Computer Science'},
        {'name': 'Steve', 'age': 42, 'major': 'Electrical Engineering'},
        {'name': 'Tina', 'age': 30, 'major': 'Computer Science'},
        {'name': 'Jack', 'age': 16, 'major': 'Mathematics'},
    ]
}

d = benedict(data)
# найдем 19-летних специалистов 
res = d.search(19)
# полученное значение res будет иметь вид 
# `[(dict, key, value), (dict, key, value)]`
for , _ , _ in res:
    print(f"Name: {['name']}, Major: {['major']}")

# Name: Charlie, Major: Mathematics
# Name: Zoe, Major: Computer Science

Benedict.standardize():

Метод Benedict.standardize() стандартизирует все ключи в benedict словаре, например 'Location Latitude' => 'location_latitude'. Такое поведение полезно при создании словаря из файла .xlsx (таблицы Excel).

>>> from benedict import benedict

data = {
    "Computer Science": {"age": 20, "first name": "Alice"}, 
    "Electrical Engineering": {"age": 21,"first name": "Bob"}
}

d = benedict(data)
d.standardize()
print(d.dump())
# {
#    "computer_science": {
#         "age": 20,
#         "first_name": "Alice"
#     },
#     "electrical_engineering": {
#         "age": 21,
#         "first_name": "Bob"
#     }
# }

Benedict.subset(keys):

Метод Benedict.subset() возвращает подмножество словаря для заданных ключей в списке keys. Можно передать один ключ или несколько ключей (в виде списка list или *args).

from benedict import benedict

data = {
    'name': 'Josh',
    'occupation': 'Data scientist',
    'skills': {
            'Python': '5 stars',
            'JavaScript': '4 stars'
    }
}

d = benedict(data)
s = d.subset(['name', 'skills.JavaScript'])
print(s)
# {'name': 'Josh', 'skills': {'JavaScript': '4 stars'}}

Benedict.swap(key1, key2):

Метод Benedict.swap() меняет местами значение ключей key1 и key2.

from benedict import benedict
data = {'Python': '5 stars', 'JS': '4 stars', 'Java': '3 stars'}
d = benedict(data)
d.swap("Java", "JS")
print(d)
# {'Python': '5 stars', 'JS': '3 stars', 'Java': '4 stars'}

Benedict.traverse(fn):

Метод Benedict.traverse() проходит по словарю, и вызывает функцию обратного вызова fn с аргументами (dict, key, value) на каждом его элементе.

from benedict import benedict

data = {
    'name': 'Josh',
    'occupation': 'Data scientist',
    'skills': {
            'Python': '5 stars',
            'JavaScript': '4 stars'
    }
}

d = benedict(data)
def f(d, key, value):
    print(f"key: {key} => value: {value}")

print(d.traverse(f))
# key: name => value: Josh
# key: occupation => value: Data scientist
# key: skills => value: {'Python': '5 stars', 'JavaScript': '4 stars'}
# key: Python => value: 5 stars
# key: JavaScript => value: 4 stars

Benedict.unique():

Метод Benedict.unique() удаляет повторяющиеся значения из словаря Benedict.

from benedict import benedict
data = {'a': 1, 'b': 2, 'c': 3, 'd': 3, 'e': 1}
d = benedict(data)
d.unique()
print(d)
# {'a': 1, 'b': 2, 'c': 3}