Когда-то вы уже писали функцию merge
, которая производит слияние двух отсортированных кортежей.
Давай-те её немного переработаем.
Введём систему проверок:
- если один из параметров не является итерируемым объектом, то вызовите исключение
StopIteration
; - если значения входных параметров содержат «неоднородные» данные, то вызовите исключение
TypeError
; - если один из параметров не отсортирован, то вызовите исключение
ValueError
.
Проверки следует проводить в указанном порядке.
Если параметры прошли все проверки, верните итерируемый объект, являющийся слиянием двух переданных.
Примечание
В решении не должно быть вызовов требуемых функций.
Пример
Ввод
print(*merge(35, (1, 2, 3)))
Вывод
Вызвано исключение StopIteration
Ввод
print(*merge([3, 2, 1], range(10)))
Вывод
Вызвано исключение ValueError
Решение
Чуть более сложная версия задачи J. Слияние
Разница только в том, что ее надо оформить функцией и, дополнительно, надо проверить передаваемые параметры на соответствие условиям.
Проверить итерируем ли объект можно несколькими способами:
1. Можно проверить с помощью try/except результат выполнения функции iter(obj), которая попытается итерировать объект.
2. Можно проверить у объекта наличие атрибута __iter__ с помощью фунции hasattr(): hasattr(obj, ‘__iter__’)
Проверка неоднородности данных довольна тривиальна – надо убедиться, что все элементы последовательности имеют один и тот же тип данных, что и у первого элемента. Одна из проблем, с которой сталкиваются учащиеся – проверка однородности (консистентности) каждой последовательности отдельно. В этом подходе есть пробелма – обе последовательности могут быть консистентны относительно первого элемета, но быть разными относительно друг-друга. Пример таких последовательностей – список строк и список чисел. Решается проблема довольно просто – сначала сливаем последовательности в одну, а потом проверяем на однородность.
Проверка на отсортированность тривиальна. Каждый последующий элемент не должен быть меньше предыдущего. Можно оформить с помощью all/any. А можно схитрить и использовать конструкцию queue != sorted(queue).
По завершении проверок можно слить данные с помощью ранее написанного алгоритма.
Посмотреть код
Решение
def check_queue_iterated(*queues):
for queue in queues:
try:
iter(queue)
except TypeError:
raise StopIteration
def check_queue_consistence(*queues):
queue = []
for queue_in_queues in queues:
queue.extend(list(queue_in_queues))
if not all(type(member) is type(queue[0]) for member in queue):
raise TypeError
def check_queue_sorted(*queues):
for queue in queues:
if list(queue) != sorted(queue):
raise ValueError
def merge(queue_1, queue_2):
check_queue_iterated(queue_1, queue_2)
check_queue_consistence(queue_1, queue_2)
check_queue_sorted(queue_1, queue_2)
queue_1n = list(queue_1)
queue_2n = list(queue_2)
sequence = []
while queue_1n and queue_2n:
if queue_1n[0] > queue_2n[0]:
sequence.append(queue_2n.pop(0))
else:
sequence.append(queue_1n.pop(0))
sequence.extend(queue_1n + queue_2n)
return sequence
Сергей, здравствуйте.
Скажите, пожалуйста, зачем в функции check_queue_sorted сделана запись «return True»?
Хотел было соврать что это издержки перфекционизма, но глянув на код понял, что это скорее невнимательность, помноженная на эти самые издержки. В таком способе реализации контроля ошибок в return, конечно, нет никакого смысла.
Спасибо, что помогаете делать код чище.
Сергей, огромное Вам спасибо за то, что так детально помогаете разобраться в специфике процесса!