[Перевод] Однострочные выражения со словарями

Некоторые замечательнеые возможности языка Python незаслуженно оставлены без внимания и многие программисты о них не знают. В этот раз речь пойдет о прекрасной возможности языка, делающей код яснее: однострочных выражениях обрабатывающих словари. Но начнем с компактных выражений обработки списков и задачи удаления неуникальных элементов коллекций.Будет интересно в основном новичкам в Python.

Однострочные выражения со спискамиСамый простой способ создать список — использовать однострочное выражение. Они довольно часто применяется, и я встречал их во многих примерах и в коде многих библиотек.Предположим, что у нас есть функция возвращающая какой-то список. Хороший пример — функция xrange (start, end), которая возвращает числа между start и end. Это генератор, и он возвращает не сразу полный список, а выдает число за числом по мере необходимости. Получение списка чисел от 1 до 10 при помощи этой функции могло бы выглядеть так:

numbers = [] for i in xrange (1, 11): numbers.append (i) Если нам нужны только четные номера, мы могли бы реализовать это следующим образом: numbers = [] for i in xrange (1, 11): if i % 2 == 0: numbers.append (i) Однострочные выражения делают код намного проще. Так выглядит выражение возвращающее список в общем виде: [ expression for item in list if conditional ] Используя его, первый пример можно переписать так: numbers = [i for i in xrange (1, 11)] , а второе так: numbers = [i for i in xrange (1, 11) if i % 2 == 0] Конечно такой синтаксис на первый взгляд может показаться странным, но когда к нему привыкнешь — код станет проще и понятнее.Удаление дубликатов Другая часто встречающаяся задача при работе с коллекциями — удаление одинаковых элементов. Ее можно решить множеством методов.Допустим мы работаем с таким списком: numbers = [i for i in xrange (1,11)] + [i for i in xrange (1,6)] Самый сложный способ удалить дубликаты, который мне встречался, выглядит так: unique_numbers = [] for n in numbers: if n not in unique_numbers: unique_numbers.append (n) Конечно и это работает, но есть решения попроще. Вы можете использовать стандартный тип множество (set). Множества не могу содержать одинаковые элементы по определению, таким образом если конвертировать список во множество — дубликаты удалятся. Но мы получим множество, а не список, поэтому если мы хотим именно список уникальных значений — нужно сконвертировать еще раз: unique_numbers = list (set (numbers)) Удаление одинаковых объектов Совсем другая ситуация с объектами или словарями. Например у нас есть список словарей, в которых одно из значений используется в качестве идентификатора: data = [ {'id': 10, 'data': '…'}, {'id': 11, 'data': '…'}, {'id': 12, 'data': '…'}, {'id': 10, 'data': '…'}, {'id': 11, 'data': '…'}, ] Удаление повторов может может быть реализовано большим или меньшим количеством кода. Конечно, чем меньше — тем лучше! Длинный вариант может выглядеть, например, так: unique_data = [] for d in data: data_exists = False for ud in unique_data: if ud['id'] == d['id']: data_exists = True break if not data_exists: unique_data.append (d) Можно получить то же результат, используя возможность, о которой я узнал пару дней назад: однострочные выражения со словарями. Они имеют похожий синтаксис на выражения со списками, но возвращают словарь:

{ key: value for item in list if conditional } Если переписать код из примера выше с использование этой фичи, останется всего одна сточка: { d['id']: d for d in data }.values () В этой строчке кода создается словарь, ключами которого являются поля, которые мы приняли за уникальный идентификатор, затем с помощью метода values () получаем все значения из созданного словаря. Т.к. словарь может содержать не больше одной записи для каждого ключа — полученный в итоге список не содержит дубликатов, что нам и требовалось.

© Habrahabr.ru