freeCodeCamp/guide/russian/computer-science/data-structures/dictionaries/index.md

13 KiB
Raw Blame History

title localeTitle
Dictionaries Словари

Словари

Предположим, у нас есть однородный список. Мы хотим подсчитать, сколько раз каждый элемент появляется в списке. Как мы можем это сделать, не используя встроенные методы Python, такие как счетчик или счетчик из модуля коллекций Python? Поиск в Google «Как подсчитать появление элемента в списке?» вернет ответы стека переполнения, указывая на метод подсчета и модуль коллекций, но в целях обучения попробуем решить проблему без использования этих инструментов.

Вот список, с которым мы будем работать:

ice_cream = ["strawberry", 
             "vanilla", 
             "vanilla", 
             "chocolate", 
             "chocolate", 
             "chocolate", 
             "banana", 
             "rum raisin", 
             "banana"] 

Этот код, используя вложенные для циклов, дает правильный ответ, сохраняя ответ в списке «count»:

count = [] 
 for flavor in ice_cream: 
  found = False 
  for entry in count: 
    if entry[0] == flavor: 
      entry[1] += 1 
      found = True 
  if not found: 
      count.append([flavor, 1]) 
 
 # Print. 
 for (entry, total) in count: 
  print (entry, total) 

Хотя этот код дает правильный ответ, в этом есть две вещи. Во-первых, это сложно. Чем больше вложенных циклов содержит программа, тем труднее понять, исправить и расширить. Более того, он неэффективен. Это не может быть проблемой в этом небольшом примере, но представьте себе список с тысячами или миллионами элементов. Сканирование списка записей каждый раз, когда мы делаем наблюдение, занимало бы очень, очень долгое время, независимо от того, насколько быстро компьютер. Эта тема более подробно рассматривается при изучении таких тем, как большая нотация O и сравнение алгоритмов поиска и сортировки.

Лучшим ответом является использование другой структуры данных, известной как словарь или карта . Эта структура данных представляет собой неупорядоченный, изменяемый набор пар ключ / значение . Подумайте о словаре, таком как телефонная книга, где ключ - это имя человека, а значение - номер телефона. Ключи в словаре образуют набор, то есть они могут появляться только один раз, и их нельзя изменить (они неизменяемы), хотя значения, связанные с ключом, могут быть изменены.

Словари создаются путем ввода пар ключ / значение внутри фигурных скобок. Чтобы получить значение, связанное с ключом, вы кладете ключ в квадратные скобки.

Вот несколько примеров кода:

ice_cream = {'chocolate' : 3, 'strawberry' : 1} 
 print (ice_cream) 
 >> {'chocolate' : 3, 'strawberry' : 1} 
 print (ice_cream['strawberry']) 
 >> 1 

Чтобы проверить, находится ли ключ в словаре, используйте k в d:

ice_cream = {'chocolate' : 3, 'strawberry' : 1} 
 if 'chocolate' in ice_cream: 
    print ('chocolate is in the list') 
 ... 
 
 del ice_cream['chocolate'] 
 if 'chocolate' in ice_cream: 
    print ('oops: why is chocolate still there?') 

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

Если ключ отсутствовал, он добавляется вместе со значением:

ice_cream = {} 
 ice_cream['chocolate'] = 33 
 ice_cream['vanilla'] = 999 # oops 
 print (ice_cream) 
 >> {'chocolate' : 33, vanilla' : 999} 
 ice_cream['vanilla'] = 9 
 print (ice_cream) 
 >> {'chocolate' : 33, vanilla' : 9} 

Используйте del d [k] , чтобы удалить запись из словаря, где d - имя словаря, а k - удаляемый ключ. Можно удалить только те записи, которые присутствуют; попытка удалить тот, который не существует, вызывает ошибку:

ice_cream = {'chocolate' : 33, vanilla' : 9} 
 del ice_cream['chocolate'] 
 print (ice_cream) 
 >> {'vanilla' : 9} 
 del ice_cream['strawberry'] 
 >> Traceback (most recent call last): 
   File "<stdin>", line 5, in <module> 
   KeyError: 'strawberry' 

Loops Так как словари представляют собой коллекции (вместе со списками, кортежами и наборами), мы собираемся содержание. Мы делаем это с циклом for, который поочередно присваивает каждому из ключей словаря переменную цикла:

ice_cream = {'chocolate' : 183, 
             'vanilla' : 71, 
             'strawberry' : 63, 
             'banana', 1} 
 for flavor in ice_cream: 
  print (flavor, ice_cream[flavor]) 
 
 >> 'banana' 1 
   'vanilla' 71 
   'chocolate' 183 
   'strawberry' 63 

Как и в случае с установленными элементами, Python перебирает записи в словаре в произвольном порядке. Нет гарантии, что они будут отображаться в алфавитном порядке или в порядке, они были добавлены в словарь. Обратите внимание, кстати, что переплетение словарей немного отличается от циклов над списками. Когда Python перебирает список, значения в списке присваиваются переменной цикла. Когда он перебирает словарь, с другой стороны, он назначает ключи. Дизайнеры Python решили сделать это, потому что:

  • петля над индексами списка не очень интересна, так как программа всегда будет получать последовательность 0, 1, 2, ...; а также
  • гораздо проще перейти от словарного ключа к соответствующему значению чем принимать значение и находить соответствующий ключ.

Методы словаря Словари - это объекты, как и списки, кортежи и наборы. Несколько общих методов словаря:

  • d.clear () - очистить словарь
  • d.get (x, 99) - Возвращает значение, связанное с ключом, или значение по умолчанию, если ключ отсутствует.
  • d.keys () - клавиши возврата
  • d.items () - возвращает список пар ключей, значений
  • d.values () - возвращает значения в виде списка, значения могут быть не уникальными
  • d.update () - обновить словарь с содержимым другого

Одним распространенным применением элементов является цикл над ключами и значениями в словаре вместе: for (key, value) в словаре.items (): ... делать что-то с ключом и ценностью ...

Это неэффективно для больших словарей, поскольку items () фактически создает список пар (ключ, значение). Аналогичный метод, называемый iteritems (), передает эти пары один за другим по требованию: для (ключ, значение) в словаре.iteritems (): ... делать что-то с ключом и ценностью ...

Вернемся к исходному примеру - как подсчитать количество элементов в списке ice_cream с помощью словаря?

# Count all the flavors. 
 ice_cream = ["strawberry", 
             "vanilla", 
             "vanilla", 
             "chocolate", 
             "chocolate", 
             "chocolate", 
             "banana", 
             "rum raisin", 
             "banana"] 
 
 count = {} 
 for flavor in ice_cream: 
  if flavor in count: 
    count[flavor] = count[flavor] + 1 
  else: 
    count[flavor] = 1 
 
 # Print. 
 for b in count: 
  print (b, count[b]) 

Для этого мы создаем словарь, который изначально пуст. Каждый раз, когда мы просматриваем список ice_cream, мы проверяем чтобы узнать, находится ли этот вкус уже в словаре count. Если это так, добавим его к его счету. Если это не так, мы добавляем имя в словарь со значением 1.

Мы можем немного сократить эту программу, используя метод dict.get () . Это возвращает значение, связанное с ключом или некоторым значением по умолчанию, которое мы предоставляем. В этом случае мы получаем либо количество раз, когда мы уже видели вкус, либо ноль, добавляем его к тому, какое значение возвращает метод, и сохраняем его в словаре:

# Count all the flavors. 
 count = {} 
 for flavor in ice_cream: 
  count[flavor] = count.get(flavor, 0) + 1 
 
 # Print. 
 keys = count.keys() 
 keys.sort() 
 for b in keys: 
  print (b, count[b]) 
 
 # Print. 
 for key in sorted(count): 
  print (key, count[key]) 

Обратите внимание, что мы используем два разных способа печати ключа и значения: один использует сортированный метод Python, а другой - нет.

Если бы мы хотели напечатать ароматы по порядку частоты, нам нужно инвертировать словарь . Это означает, что нам нужно использовать значения как ключи, а ключи - как значения. Поскольку нет никакой гарантии, что значения уникальны, нам нужно предпринять шаги, чтобы избежать столкновений .

Решение состоит в том, чтобы использовать какую-то коллекцию, такую ​​как список, для хранения значений инвертированного словаря. Если мы пройдем по этому маршруту, обратный словарь, показанный ранее, будет {1: ['a', 'b', 'c']}. Вот программа, которая сделает то, что мы хотим:

ice_cream = ["strawberry", 
             "vanilla", 
             "vanilla", 
             "chocolate", 
             "chocolate", 
             "chocolate", 
             "banana", 
             "rum raisin", 
             "banana"] 
 
 # Count all the flavors. 
 count = {} 
 for flavor in ice_cream: 
  count[flavor] = count.get(flavor, 0) + 1 
 
 # Invert the dictionary. 
 freq = {} 
 for (flavor, times) in count.items(): 
  if times in freq: 
    freq[times].append(flavor) 
  else: 
    freq[times] = [flavor] 
 
 # Print. 
 for key in freq: 
  for flavor in sorted(freq[key]): 
    print (key,":", " ", flavor) 

Дополнительная информация: