Skip to content

Latest commit

 

History

History
211 lines (156 loc) · 12.7 KB

05-From-Tables-to-Lists.md

File metadata and controls

211 lines (156 loc) · 12.7 KB

4 От Таблиц к Спискам

В предыдущей главе мы начали работать с составными данными, представленными в виде таблиц, и познакомились с несколькими табличными операциями, с помощью которых мы можем быстро ответить на многие непростые вопросы о наших данных. У всех этих операций есть два общих для них свойства: во-первых, все операции являются построчными, ни одна из этих операций не позволяет задать вопрос сразу про какой-то конкретный столбец; во-вторых, каждая операция производит в результате всегда то же самое, что и получает --- таблицу. Как мы уже знаем, существует множество различных типов данных: числа, строки, булевы значения, картинки и т. д., и нам бы хотелось иметь возможность получать на основе данных таблицы не ещё одну --- новую --- таблицу, а данные какого-нибудь другого вида, например, число. В этой главе мы узнаем, как можно избавиться от этих двух ограничений, введя по ходу новый тип данных.

4.1 Базовые Статистические Вопросы

Есть ещё довольно много вопросов, которые можно было бы задать о наших данных. К примеру:

  • Самая популярная композиция в плейлисте;

  • Самый большой файл в файловой системе;

  • Самый низкий человек в классе;

  • Средняя цена за один товар в магазине;

  • Список различных имейлов отправителей во входящих на почте;

  • Город Свердловской области с наибольшим количеством заболевших COVID-19.

Для ответа на эти и другие похожие вопросы нам нужно будет вычислять: максимум, минимум, среднее значение, медиану, моду и т. д. В Pyret встроены некоторые из этих статистических функций, обнаружить которые можно в пакетах math и statistics.

4.2 Извлечение Столбца из Таблицы

Мы уже, в принципе, способны это сделать, использовав известный нам select:

songs = table: title, artist, play-count
  row: "Harry Styles", "Adore You", 0
  row: "Blinding Lights", "The Weeknd", 5
  row: "Memories", "Maroon 5", 97
  row: "The Box", "Roddy Ricch", 25
end
select play-count from songs end

но в итоге мы получим столбец в таблице, т. е. по сути опять таблицу (состоящую из одного столбца). Чтобы получить ответы на вопросы выше, нам нужны операции, которые бы обрабатывали всю эту совокупность чисел (значения play-count) целиком, что при имеющихся операциях сделать невозможно, т. к. каждая из них работает построчно, т. е. за один раз они могут обработать только одно число, а не всю совокупность сразу.

Извлечённый столбец имеет структуру более общую, чем сама таблица, и называется такая структура списком. Чтобы получить какой-то столбец таблицы в виде списка, нужно воспользоваться операцией extract:

>>> extract play-count from songs end
[list: 0, 5, 97, 25]

Отличие select от extract заключается в том, что select производит таблицу, а extract --- список.

4.3 Изучаем Списки

Списки и таблицы из одного столбца очень похожи:

  • во-первых, и на списках, и на таблицах задан порядок. Т. е. имеет смысл говорить о «первом», «втором», «последнем» и т. д. элементе списка;

  • во-вторых, у всех элементов списка, как и у всех значений в одном столбце, должен быть один и тот же тип.

Ключевое же отличие состоит в том, что у списка нет «имени столбца»; список анонимен. Т. е. список сам по себе не говорит о том, какую информацию он отражает (имена людей, балансы банковских счетов, количество товаров в магазине, ...).

4.3.1 Списки как Анонимные Данные

На самом деле, анонимные данные не являются чем-то новым. Все виды данных, с которыми мы уже успели поработать, являются анонимными. Любое отдельно взятое число никак не говорит нам о том, представлением чего оно является. Мы сами интерпретируем конкретные значения. А чтобы не забыть об этом, даём значениям осмысленные имена путём их связывания. То же самое можно сказать и о булевых значениях, и о строках, и о картинках. Единственным исключением из этого являются таблицы, внутри которых уже заключена эта интерпретация.

Универсальность анонимных данных является, с одной стороны, их преимуществом, а с другой, --- недостатком. Недостаток состоит в том, что в этих данных нет заранее заложенной интерпретации, по этой причине данные могут быть истолкованы ошибочно, например, по нашей же невнимательности. В то же время, универсальность позволяет нам использовать одни и те же данные в разных контекстах. Значение 7 можно использовать в программах и как количество дней недели, и как телефонный код страны, и как что угодно ещё, что вы можете себе вообразить.

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

4.3.2 Создание Списков

Мы узнали, как можно создать список из таблицы, используя extract. Очевидно, мы также можем создавать списки и без таблиц напрямую:

[list: 1, 2, 3]
[list: -1, 5, 2.3, 10]
[list: "a", "b", "c"]
[list: "Это", "список", "слов"]

Списки являются значениями, поэтому мы можем давать им имена

shopping-list = [list: "muesli", "fiddleheads"]

, которые впоследствии можно передавать функциям в качестве аргументов и т. д.

Упражнение: основываясь на примерах определений списков выше, угадайте, как можно задать пустой список, т. е. список, в котором нет ни одного элемента.

4.4 Работа со Списками

4.4.1 Встроенные Операции

Подключив библиотеки math и statistics

include math
include statistics

мы получаем доступ к следующим полезным функциям:

  • max вычисляет максимальный элемент списка;

  • min вычисляет минимальный элемент списка;

  • mean вычисляет среднее значение элементов списка;

  • stdev вычисляет стандартное отклонение значений списка.

И тогда код

pcs = extract play-count from songs end
most-played-count = max(pcs)
least-played-count = min(pcs)

вычислит наибольшее и наименьшее количество прослушиваний из таблицы с песнями.

Подобным же образом мы можем вычислить максимальный и минимальный рост из таблицы с людьми:

hts = extract height from people end
tallest-height = max(hts)
shortest-height = min(hts)

Упражнение: создайте таблицу с тремя людьми такую, что после выполнения кода выше значения 72 и 42 будут связаны с именами tallest-height и shortest-height соответственно.

4.4.2 Комбинируем Списки и Таблицы

Заметьте, что в вопросах речь шла всё-таки о другом: там не спрашивалось о наибольшем росте, там спрашивалось о человеке с наибольшим ростом, и не о количестве прослушиваний, а о песне с максимальным количеством прослушиваний. Поскольку для работы с ростами и прослушиваниями в формате списков мы вырезали их из контекста, в котором они были, находясь в таблице, нельзя теперь определить, к каким людям или песням относятся эти значения. Чтобы это сделать, нам необходимо вернуться к таблице и выбрать те строки, которые связаны с нужным значением:

tallest-people = sieve people using height:
  height == tallest-height
end

Таким образом, для получения правильного ответа на поставленный вопрос нам нужно написать

hts = extract height from people end
tallest-height = max(hts)
sieve people using height:
  height == tallest-height
end

Упражнение: напишите выражение для определения песен с наибольшим количеством прослушиваний по аналогии с кодом выше.

Упражнение: объясните, почему в имени tallest-people используется множественное число (people --- люди).