Сборник. Сборник упражнений
Скачать 1.68 Mb.
|
Глава 6 Словари Между списками и словарями много общего. Как и списки, словари (dic- tionary) позволяют хранить большое количество однородной информа- ции в одной переменной. Каждый элемент списка обладает собственным уникальным целочисленным индексом, и эти индексы располагаются по возрастанию, начиная с нуля. Так же и в словарях каждое значение (value) строго ассоциировано с ключом (key), при этом ключи обладают гораздо большей гибкостью по сравнению с индексами списков. Ключи словарей могут быть как целочисленными, так и числами с плавающей запятой или строками. Еще стоит отметить, что числовые ключи в словарях со- всем не обязательно должны начинаться с нуля и располагаться в строгой последовательности по возрастанию. Будучи строковыми, ключи могут содержать любую текстовую информацию, включая пустые строки. Един- ственное условие, объединяющее индексы в списках с ключами в слова- рях, состоит в их уникальности. Каждый ключ в словаре должен быть ассоциирован ровно с одним зна- чением, которое может быть целочисленным, числом с плавающей за- пятой, строкой или булевым значением. Кроме того, значение само по себе может представлять список или словарь. Ключ словаря с ассоции- рованным с ним значением часто упоминается как пара ключзначение (key-value pair). Хотя ключи в словаре должны быть строго уникальными, подобное ограничение не распространяется на его значения. Следова- тельно, одинаковые значения могут быть ассоциированы с разными клю- чами одного и того же словаря. Начиная с версии Python 3.7 все пары ключ-значение в словарях хра- нятся в том порядке, в котором были добавлены. В более ранних верси- ях Python такая зависимость не была гарантирована. Каждая новая пара ключ-значение при добавлении в словарь отправляется в его конец. Меха- низма для того, чтобы вставить новую пару в середину словаря, просто не существует. Удаление любой пары ключ-значение не оказывает влияния на порядок следования оставшихся элементов в словаре. Переменная, хранящая словарь, создается так же, как и остальные, – при помощи оператора присваивания. Пустой словарь, не содержащий пар Словари 113 ключ-значение, может быть объявлен как сочетание открывающей и за- крывающей фигурных скобок – {}. Если вам необходимо создать непустой словарь, перечислите в фигурных скобках пары ключ-значение через за- пятую. При этом сами ключи и ассоциированные с ними значения должны разделяться двоеточием. В следующем фрагменте кода создается словарь с тремя парами ключ-значение, где ключ – это строка, а значение – число с плавающей запятой. Каждая пара в этом словаре представляет конкрет- ную математическую константу. После создания словаря можно вывести его на экран при помощи стандартной функции print. constants = {"pi": 3.14, "e": 2.71, "root 2": 1.41} print(constants) 6.1. ч тение , доБавление и изменение словарей Получить доступ к значению в словаре можно подобно тому, как мы об- ращались к элементам списков. Если индекс нужного элемента в списке нам известен, для обращения к нему достаточно написать имя списка вместе с этим индексом, заключенным в квадратные скобки. Так же и со словарями – при известном ключе можно получить доступ к ассоцииро- ванному с ним значению посредством указания имени словаря и ключа в тех же квадратных скобках. Изменение значения в словаре и добавление новой пары ключ-значение выполняются при помощи оператора присваивания. При этом имя слова- ря с ключом в квадратных скобках помещается слева от знака равенства, а ассоциированное с этим ключом значение – справа. Если элемент с та- ким ключом уже существует в словаре, его значение будет перезаписано. В противном случае будет создана новая пара ключ-значение. Рассмотрим эти операции на примере. # Создадим словарь с двумя парами ключ–значение results = {"pass": 0, "fail": 0} # Добавим третью пару ключ–значение results["withdrawal"] = 1 # Обновим значения двух ключей в словаре results["pass"] = 3 results["fail"] = results["fail"] + 1 # Выведем значения, ассоциированные с ключами fail, pass и withdrawal соответственно print(results["fail"]) 114 Упражнения print(results["pass"]) print(results["withdrawal"]) При запуске данной программы будет создан словарь results с двумя ключами: pass и fail. Значения, ассоциированные с этими ключами, мы сделали нулевыми. Далее словарь пополняется еще одной парой с ключом withdrawal и значением 1. После этого значение, ассоциированное с клю- чом pass, меняется на 3 при помощи оператора присваивания. В следую- щей строке происходит обращение к значению ключа fail, к которому прибавляется единица, и новое значение сохраняется в паре с тем же ключом fail, заменяя предыдущее значение. При отображении значений первой будет выведена единица (значение, ассоциированное с ключом fail ), затем тройка, соответствующая ключу pass, и снова единица – на этот раз представляющая значение ключа withdrawal. 6.2. у даление пары ключ - значение Пару ключ-значение из словаря можно удалить при помощи знакомого уже нам метода pop. В качестве аргумента этому методу должен быть пере- дан ключ элемента, который требуется удалить. При выполнении метод удалит из списка как ключ, так и ассоциированное с ним значение. В от- личие от списка, извлечь последнюю пару ключ-значение из словаря при помощи вызова метода pop без аргументов невозможно. Метод pop возвращает значение, ассоциированное с ключом удаленной пары из словаря. Это значение может быть сохранено в переменной по- средством оператора присваивания или использовано в других целях – например, в арифметическом выражении или для передачи в качестве аргумента в другую функцию либо метод. 6.3. д ополнительные операции со словарями После заполнения словаря парами ключ-значение может понадобиться выполнить различные действия с данными. Например, вам может потре- боваться информация о том, сколько всего пар ключ-значение находится в словаре и присутствует ли в нем пара с конкретным ключом или значе- нием. В Python реализовано сразу несколько функций, методов и опера- торов, позволяющих извлекать нужные сведения о словарях. К примеру, функция len, которой мы пользовались для определения размера списка, вполне применима и к словарям – она выдает текущее Словари 115 количество пар ключ-значение, присутствующих в словаре. В качестве единственного параметра функции следует передать переменную, пред- ставляющую словарь, и на выходе мы получим количество пар ключ- значение в указанном словаре. Если словарь на данный момент является пустым, функция вернет ноль. Также знакомый нам оператор in может быть использован для опреде- ления того, входит ли в словарь интересующий нас ключ или значение. Для поиска ключа в словаре достаточно написать условное выражение, поместив ключ слева от оператора in, а имя словаря – справа. Оператор вернет True при наличии искомого ключа в словаре и False в обратном слу- чае. Результат оператора in может быть использован везде, где допустимо применять булевы значения, например в условных блоках инструкций if или while. Для определения наличия в словаре нужного вам значения необходимо использовать оператор in совместно с методом values. В этом случае ис- комое значение помещается слева от оператора in, а имя словаря с при- мененным к нему методом values – справа. В следующем фрагменте кода мы определим, присутствует ли в списке значений словаря d значение, находящееся в переменной x. if x in d.values(): print("В словаре d есть как минимум одно значение", x) else: print("В словаре d не присутствует значение", x) 6.4. ц иклы и словари Цикл for может быть использован для осуществления итераций по ключам словаря, как показано ниже. На каждой итерации ключ словаря сохраня- ется во внутренней переменной цикла k. # Создаем словарь constants = {"pi": 3.14, "e": 2.71, "root 2": 1.41} # Выводим на экран все ключи и значения в отформатированном виде for k in constants: print("Значение, ассоциированное с ключом", k, ": ", constants[k]) Сначала создается словарь с именем constants, в котором хранятся не- которые математические константы в виде пар ключ-значение. Цикл for открывает итерации по словарю. На первой итерации ключ pi сохраняется во временную переменную цикла k, и выполняется тело цикла с выво- дом на экран первой пары ключ-значение из списка. После этого цикл запускается вновь, и в переменную k уже попадает ключ e. В теле цикла 116 Упражнения на экран выводится соответствующая строка со значением 2,71. На за- ключительном проходе по словарю мы узнаем, что квадратный корень из двух равен 1,41. Циклом for также можно воспользоваться для осуществления итераций по значениям словаря. Это легко реализовать при помощи метода values, не принимающего аргументов и создающего коллекцию значений слова- ря, к которому он применен. В следующем фрагменте кода мы рассчита- ем сумму всех сохраненных в нашем словаре математических констант. Выражение constants.values() вернет коллекцию, состоящую из значений 3,14, 2,71 и 1,41. Каждое из этих значений во время итераций сохраняется во временной переменной цикла v, что позволяет рассчитать их сумму вовсе без обращения к ключам. # Создаем словарь constants = {"pi": 3.14, "e": 2.71, "root 2": 1.41} # Рассчитаем сумму значений в словаре total = 0 for v in constants.values(): total = total + v # Выводим результат print("Сумма значений составляет", total) Иногда бывает удобнее обращаться к словарям при помощи циклов while , а не for. В следующем фрагменте кода пользователь должен ввести пять уникальных значений с клавиатуры, после чего на экране будут по- казаны все введенные данные со значением счетчика, который увели- чивается на единицу всякий раз, когда пользователь вводит строку, уже присутствующую в словаре. # Считаем, сколько раз пользователь ввел каждое значение counts = {} # Цикл, пока количество уникальных значений в словаре не достигнет пяти while len(counts) < 5: s = input("Введите строку: ") # Если в словаре уже есть такой ключ, увеличиваем count на 1. # Иначе добавляем пару к словарю со значением count, равным 1. if s in counts: counts[s] = counts[s] + 1 else: counts[s] = 1 # Выводим все строки и счетчики for k in counts: print(k, "появилась в словаре", counts[k], "раз") Словари 117 Программа начинается с создания пустого словаря. После этого запус- кается цикл while с проверкой на количество пар ключ-значение в слова- ре. Поскольку словарь пока пуст, условное выражение вернет True, и будет запущено тело цикла. На каждой итерации пользователь будет вводить строку с клавиатуры. После этого при помощи оператора in будет определено, присутствует ли введенный пользователем ключ в списке. Если да, то ассоциированный с этим ключом счетчик (значение) будет увеличен на единицу. В против- ном случае словарь пополнится новой парой ключ-значение. Цикл будет продолжаться, пока пользователь не введет пять уникальных строк с кла- виатуры. После этого на экран будут выведены все пары ключ-значение из списка. 6.5. с ловари как аргументы и возвращаемые значения функций Словари могут быть переданы в функцию подобно значениям других ти- пов. Как и в случае со списками, изменение переменной параметра, хра- нящей переданный словарь, может привести к модификации источника. Например, удаление, изменение или добавление пары ключ-значение неизбежно приведет к соответствующему изменению аргумента. В то же время присвоение переменной параметра другого значения (когда слева от знака равенства указывается только переменная без квадратных ско- бок) аргумента не затронет. Как и в случае с переменными других типов, функция может возвращать словарь при помощи ключевого слова return. 6.6. у пражнения Несмотря на то что многие упражнения из данного раздела могут быть решены при помощи списков и выражений if, большинство из них имеют решения и с применением словарей. Поскольку мы в этой главе говорим главным образом о словарях, используйте их в своих программах вместе с другими конструкциями языка Python, которые вы изучили ранее в книге. Упражнение 136. Поиск по значению (Решено. 45 строк) Напишите функцию с названием reverseLookup, которая будет осуществ- лять поиск всех ключей в словаре по заданному значению. Функция должна принимать в качестве параметров словарь и значение для поиска 118 Упражнения и возвращать список ключей (он может быть пустым) из этого словаря, соответствующих переданному значению. В основной программе продемонстрируйте работу функции путем соз- дания словаря и поиска в нем всех ключей по заданному значению. Убе- дитесь, что функция работает корректно при наличии нескольких ключей для искомого значения, одного ключа и их отсутствии. Ваша програм- ма должна запускаться только в том случае, если она не импортирована в виде модуля в другой файл. Упражнение 137. Две игральные кости (Решено. 43 строки) В данном упражнении мы будем симулировать 1000 выбрасываний игральных костей. Начнем с написания функции, выполняющей случай- ное выбрасывание двух обычных шестигранных костей. Эта функция не будет принимать входных параметров, а возвращать должна число, вы- павшее в сумме на двух костях. В основной программе реализуйте симуляцию тысячи выбрасываний костей. Программа должна хранить все результаты с частотой их выпаде- ния. После завершения процесса должна быть показана итоговая таблица с результатами, похожая на ту, что представлена в табл. 6.1. Выразите частоту выпадения каждого из чисел в процентах вместе с ожидаемым результатом согласно теории вероятностей. Таблица 6.1. Выбрасывание игральных костей Исход Процент симуляции Ожидаемый процент 2 2,90 2,78 3 6,90 5,56 4 9,40 8,33 5 11,90 11,11 6 14,20 13,89 7 14,20 16,67 8 15,00 13,89 9 10,50 11,11 10 7,90 8,33 11 4,50 5,56 12 2,60 2,78 Упражнение 138. Текстовые сообщения (21 строка) Если помните, на старых мобильных телефонах текстовые сообщения на- бирались при помощи цифровых кнопок. При этом одна кнопка была ас- Словари 119 социирована сразу с несколькими буквами, а выбор зависел от количества нажатий на кнопку. Однократное нажатие приводило к появлению первой буквы в соответствующем этой кнопке списке, последующие нажатия ме- няли ее на следующую. Список символов, ассоциированных с цифровой панелью, приведен в табл. 6.2. Таблица 6.2. Символы, соответствующие кнопкам на старых телефонах Кнопка Символы 1 . , ? ! : 2 A B C 3 D E F 4 G H I 5 J K L 6 M N O 7 P Q R S 8 T U V 9 W X Y Z 0 Пробел Напишите программу, отображающую последовательность кнопок, ко- торую необходимо нажать, чтобы на экране телефона появился текст, введенный пользователем. Создайте словарь, сопоставляющий символы с кнопками, которые необходимо нажать, а затем воспользуйтесь им для вывода на экран последовательности кнопок в соответствии с введенным пользователем сообщением по запросу. Например, на ввод строки Hello, World! ваша программа должна откликнуться следующим выводом: 443355 5555666110966677755531111 . Удостоверьтесь, что ваша программа корректно обрабатывает строчные и прописные буквы. При преобразовании букв в цифры игнорируйте символы, не входящие в указанный перечень, такие как точка с запятой или скобки. Упражнение 139. Азбука Морзе (15 строк) Азбука Морзе зашифровывает буквы и цифры при помощи точек и тире. В данном упражнении вам необходимо написать программу, в которой соответствие символов из азбуки Морзе будет храниться в виде словаря. В табл. 6.3 приведена та часть азбуки, которая вам понадобится при ре- шении этого задания. В основной программе вам необходимо запросить у пользователя стро- ку. После этого программа должна преобразовать его в соответствующую последовательность точек и тире, вставляя пробелы между отдельными 120 Упражнения символами. Символы, не представленные в таблице, можно игнорировать. Например, сообщение Hello, World! может быть представлено следующей последовательностью: .... . .–.. .–.. ––– .–– ––– .–. .–.. –.. Таблица 6.3. Азбука Морзе Символ Код Символ Код Символ Код Символ Код A .– J .––– S 1 .–––– B –... K –.– T – 2 ..––– C –.–. L .–.. U ..– 3 ...–– D –.. M –– V ...– 4 ….– E N –. W .–– 5 ….. F ..–. O ––– X –..– 6 –…. G ––. P .––. Y –.–– 7 ––... H …. Q ––.– Z ––.. 8 –––.. I R .–. 0 ––––– 9 ––––. Примечание. Азбука Морзе была изобретена в XIX веке для передачи информа- ции посредством телеграфа. Она широко используется и сегодня, более чем через 160 лет после ее создания. Упражнение 140. Почтовые индексы (24 строки) Первый, третий и пятый символы в канадском почтовом индексе пред- ставляют собой буквы, а второй, четвертый и шестой – цифры. Провин- цию или территорию, которой принадлежит индекс, можно определить по первому символу индекса, как показано в табл. 6.4. Символы D, F, I, O, Q, U, W и Z в настоящее время не используются в почтовых индексах Канады. Второй символ в почтовом индексе определяет, расположен ли интере- сующий нас адрес в городе или в сельской местности. Если на этом месте стоит ноль, значит, это сельская местность, иначе город. Напишите программу, которая будет запрашивать почтовый индекс у пользователя и отображать провинцию или территорию, которой он принадлежит, с указанием того, городская это территория или сельская. Например, если пользователь введет индекс T2N1N4, программа должна определить, что речь идет о городе на территории провинции Альберта. А индекс X0A1B2 соответствует сельской местности в провинции Нунавут или в Северо-Западных территориях. Используйте словарь для хранения информации о соответствии первого символа индекса конкретной про- винции или территории. Выведите на экран соответствующее сообщение Словари 121 об ошибке, если индекс начинается с символа, который не используется для этих целей, или второй символ не является цифрой. Таблица 6.4. Почтовые индексы Канады Провинция/территория Первая буква (буквы) индекса Ньюфаундленд A Новая Шотландия B Остров Принца Эдуарда C Нью-Брансуик E Квебек G, H и J Онтарио K, L, M, N и P Манитоба R Саскачеван S Альберта T Британская Колумбия V Нунавут X Северо-Западные территории X Юкон Y Упражнение 141. Английская пропись (65 строк) Несмотря на то что популярность оплаты по чекам за последние годы серьезно снизилась, некоторые компании до сих пор используют этот спо- соб для ведения взаиморасчетов с сотрудниками и поставщиками. Сумма на чеках обычно указывается дважды: один раз цифрами, второй – про- писью на английском языке. Повторение суммы двумя разными формами записи призвано не позволить недобросовестным сотрудникам или по- ставщикам изменять сумму на чеках перед их обналичиванием. В данном упражнении вам необходимо написать функцию, принима- ющую в качестве входного параметра число от 0 до 999 и возвращающую строку прописью. Например, если значение параметра будет равно 142, функция должна вернуть следующую строку: «one hundred forty two». Ис- пользуйте один или несколько словарей вместо условных конструкций if/elif/else для выработки решения этой задачи. Напишите основную программу, в которой пользователь будет вводить числовое значение, а на экран будет выводиться соответствующая сумма прописью. Упражнение 142. Уникальные символы (Решено. 16 строк) Напишите программу, определяющую и выводящую на экран количество уникальных символов во введенной пользователем строке. Например, 122 Упражнения в строке Hello, World! содержится десять уникальных символов, а в строке zzz – один. Используйте словарь или набор для решения этой задачи. Упражнение 143. Анаграммы (Решено. 39 строк) Анаграммами называются слова, образованные путем взаимной переста- новки букв. В английском языке, например, анаграммами являются слова «live» и «evil», а в русском – «выбор» и «обрыв». Напишите программу, ко- торая будет запрашивать у пользователя два слова, определять, являются ли они анаграммами, и выводить на экран ответ. Упражнение 144. Снова анаграммы (48 строк) Понятие анаграмм не ограничивается словами, а может быть расширено до целых предложений. Например, строки «William Shakespeare» и «I am a weakish speller» являются полными анаграммами, если игнорировать пробелы и заглавные буквы. Расширьте свою программу из упражнения 143, добавив возможность проверки на анаграммы целых фраз. При анализе не обращайте внимания на знаки препинания, заглавные буквы и пробелы. Упражнение 145. Эрудит (Решено. 18 строк) В известной игре Эрудит (Scrabble™) каждой букве соответствует опреде- ленное количество очков. Общая сумма очков, которую получает игрок, составивший это слово, складывается из очков за каждую букву, входящую в его состав. Чем более употребимой является буква в языке, тем меньше очков начисляется за ее использование. В табл. 6.5 приведены все соот- ветствия букв и очков из английской версии игры. Таблица 6.5. Стоимость букв в английской версии игры Эрудит Очки Буквы 1 A, E, I, L, N, O, R, S, T и U 2 D и G 3 B, C, M и P 4 F, H, V, W и Y 5 K 8 J и X 10 Q и Z Словари 123 Напишите программу, рассчитывающую и отображающую количество очков за собранное слово. Создайте словарь для хранения соответствий между буквами и очками и используйте его в своем решении. Примечание. На игровом поле Эрудита присутствуют специальные клетки, удваива- ющие и утраивающие стоимость буквы или всего слова. В данном упражнении мы для простоты реализации проигнорируем этот факт. Упражнение 146. Карточка лото (Решено. 58 строк) Карточка для игры в лото состоит из пяти колонок, в каждой из которых – пять номеров. Колонки помечены буквами B, I, N, G и O. Под каждой буквой могут быть номера в своем диапазоне из 15 чисел. А именно под буквой B могут присутствовать числа от 1 до 15, под I – от 16 до 30, под N – от 31 до 45 и т. д. Напишите функцию, которая будет создавать случайную карточку лото и сохранять ее в словаре. Ключами словаря будут буквы B, I, N, G и O, а зна- чениями – списки из пяти чисел, располагающихся в колонке под каждой буквой. Создайте еще одну функцию для отображения созданной карточ- ки лото на экране со столбцами с заголовками. В основной программе создайте карту лото случайным образом и выведите ее на экран. Ваша программа должна запускаться только в том случае, если она не импор- тирована в виде модуля в другой файл. Примечание. Как вы знаете, в настоящих карточках для игры в лото присутствуют пустые клетки в столбцах. Мы не будем реализовывать эту особенность в нашей про- грамме. Упражнение 147. Проверка карточки (102 строки) Карточка для игры в лото считается выигравшей, если в ней на одной ли- нии расположились пять выпавших номеров. Обычно игроки зачеркивают номера на своих карточках. В данном упражнении мы будем обнулять в словаре выпавшие номера. Напишите функцию, принимающую на вход карточку в качестве пара- метра. Если карточка содержит последовательность из пяти нулей (по вер- тикали, горизонтали или диагонали), функция должна возвращать True, в противном случае – False. 124 Упражнения В основной программе вы должны продемонстрировать на примере работу функции, создав и отобразив несколько карточек с указанием того, какие из них выиграли. В вашем примере должно быть как минимум по одной карточке с выигрышем по вертикали, горизонтали и диагонали, а также карточки, на которые выигрыш не выпал. При решении этой за- дачи воспользуйтесь функциями из упражнения 146. Подсказка. Поскольку отрицательных чисел на карточке лото быть не может, нахож- дение линии со всеми нулями сводится к поиску последовательности чисел, сумма которых равна нулю. Так вам будет легче решить это упражнение. Упражнение 148. Играем в лото (88 строк) В данном упражнении мы напишем программу, выполняющую симуля- цию игры в лото с одной картой. Начните с генерирования списка из всех возможных номеров для выпадения (от B1 до O75). После этого переме- шайте номера в хаотичном порядке, воспользовавшись функцией shuffle из модуля random. Вытаскивайте по одному номеру из списка и зачерки- вайте номера, пока карточка не окажется выигравшей. Проведите 1000 си- муляций и выведите на экран минимальное, максимальное и среднее ко- личество извлечений номеров, требующееся для выигрыша. При решении этой задачи вы можете воспользоваться функциями из упражнений 146 и 147. |