Генератори словників

      Деякі замечательнеие можливості мови Python незаслужено залишені без уваги і багато програмісти про них не знають. Цього разу мова піде про прекрасну можливості мови, що робить код ясніше: генератори словників — однорядкові вираження повертають словник. Але почнемо з компактних генераторів списків і завдання видалення неунікальний елементів колекцій.
 
Буде цікаво в основному новачкам в Python.
 
 
Генератори списків
 
Найпростіший спосіб створити список — використовувати однорядкове вираз — генератор списку. Вони досить часто застосовується, і я зустрічав їх в багатьох прикладах і в коді багатьох бібліотек.
Припустимо, що у нас є функція повертає якийсь список. Хороший приклад — функція range (start, end) , яка повертає числа між start і end . Починаючи з версії Python 3.0 вона реалізована як генератор і повертає не відразу повний список, а видає число за числом по мірі необхідності. У Python 2. * Для цього використовувалася функція xrange () . Отримання списку чисел від 1 до 10 за допомогою цієї функції могло б виглядати так:
 
numbers = []
for i in range(1, 11):
    numbers.append(i)

Якщо нам потрібні тільки парні номери, ми могли б реалізувати це таким чином:
 
numbers = []
for i in range(1, 11):
    if i % 2 == 0:
        numbers.append(i)

Генератори словників роблять код набагато простіше. Так виглядає вираз повертає список в загальному вигляді:
 
[ expression for item in list if conditional ]

Використовуючи його, перший приклад можна переписати так:
 
numbers = [i for i in range(1, 11)]

а другий так:
 
numbers = [i for i in range(1, 11) if i % 2 == 0]

Звичайно такий синтаксис на перший погляд може здатися дивним, але коли до нього звикнеш — код стане простіше і зрозуміліше.
 
 
Видалення дублікатів
Інша часто зустрічається завдання при роботі з колекціями — видалення однакових елементів. Її можна вирішити безліччю методів.
Припустимо ми працюємо з таким списком:
 
numbers = [i for i in range(1,11)] + [i for i in range(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 ​​() отримуємо всі значення з створеного словника. Т.к. словник може містити не більше одного запису для кожного ключа — отриманий в результаті список не містить дублікатів, що нам і було потрібно.
  
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.