Статья Автор: Деникина Н.В., Деникин А.В.

Программное решение

Важное замечане
Если ваш опыт программирования не слишком большой, то лучше пропустить эту тетрадь и следующее задание и перейти сразу к заданию 15. Данное задание решается достаточно легко фильтрами, напрямую в электронных таблицах. 

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

 

Задача

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


Шаг первый: прочитать файлы

Питон не открывает .xls, поэтому каждый лист базы сохраняем отдельным файлом csv. Листа три — файлов тоже три.

dv  = open('dvizhenie.csv', encoding='UTF-8').readlines()
tov = open('tovar.csv',     encoding='UTF-8').readlines()
mag = open('magazin.csv',   encoding='UTF-8').readlines()

readlines() возвращает список строк: сколько строк в файле, столько элементов в списке.

encoding='UTF-8' обязателен — в файлах русские буквы, без указания кодировки они прочитаются как мусор.


Шаг второй: добраться до полей

Одна строка списка — это пока сплошной текст. Чтобы работать с отдельными значениями, режем её по разделителю.

Строка файла и её поля1;01.06.2021;M1;4;180;Поступление;75split(";")1ID оп.[0]01.06.2021Дата[1]M1Магазин[2]4Артикул[3]180Кол-во[4]ПоступлениеТип[5]75Цена[6]

После split(';') получается список полей. Обращаемся по номеру, счёт с нуля: pole[1] — дата, pole[4] — количество, pole[6] — цена.

strip('\n') нужен, чтобы убрать перевод строки: без него последнее поле было бы '75\n', хотя int() с ним справился бы. Но если бы последним элементом была строка, то можно было бы словить ошибку.


Шаг третий: подготовить справочники

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

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

Порядок действий1.Прочитать три файла2.Из справочника товаров выписать артикулы сметаны3.Из справочника магазинов выписать номера Октябрьского района4.Пройти по движению товаров и накопить суммушаги 2 и 3 выполняются по одному разу, до основного цикла

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


Как собрать список артикулов

smetana = []
for line in tov:
    pole = line.strip('\n').split(';')
    if 'сметана' in pole[2].lower():
        smetana.append(pole[0])

Читается прямо: разбираем строку на поля, смотрим наименование и, если в нём есть нужное слово, запоминаем артикул.

Два места, где легко ошибиться.

Берём поле, а не символ. line — это строка целиком, поэтому line[2] вернёт третью букву. Поле появляется только после split.

line[2]      →  'С'                 буква
pole[2]      →  'Сметана 15%'       поле

Приводим к строчным. В базе написано «Сметана» с большой буквы, а ищем мы «сметана». Без .lower() совпадения не будет.

И ищем через in, а не сравниваем целиком: сметаны в базе два вида — 15% и 25%, и нужны оба.


Решение целиком

Последний шаг — пройти по движению товаров, отобрать нужные операции и накопить сумму. Стоимость одной операции — это количество упаковок, умноженное на цену.

▶ Запусти.



Что получилось

92635

Разберём два места в основном цикле.
 

Именованные переменные

nomer_mag = pole[2]
artikul   = pole[3]
kolvo     = int(pole[4])

Можно было писать pole[4] прямо в условии, но тогда через десять строк придётся вспоминать, что там за поле. С именами код читается сам.

Обрати внимание: количество и цена сразу переводятся в число через int(). Из файла всё приходит текстом, а перемножать надо числа.
 

День из даты

den = int(pole[1][:2])      # '03.06.2021' → '03' → 3

Берём первые два символа и переводим в число. Именно в число: как текст '10' оказывается меньше '5', потому что сравнение идёт по символам — единица меньше пятёрки.


Где теряют ответ

Отбор по отделу вместо наименования

В справочнике товаров есть столбец «Отдел». В отделе «Молоко» лежат не только молоко и сметана, но и кефир, творог, масло и яйцо. Если отбирать по отделу, в выборку попадёт лишнее.

«Сметана всех видов» — это про наименование товара.

Забыли про тип операции

В таблице движения есть и поступления, и продажи. Вопрос про проданное — значит поступления в выборку не входят.

Стоимость перепутана с количеством

«Общая стоимость» — это количество, умноженное на цену. Если накапливать только количество, получится число упаковок, а не рубли.


Проверь себя


Что вернёт readlines()?


Почему line[2] не даёт третье поле?


Зачем .lower() при поиске сметаны?


Почему день сравнивают числом, а не текстом?


Спрашивают общую стоимость. Что накапливать?

Печать