E. Слияние с проверкой

Когда-то вы уже писали функцию 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).

По завершении проверок можно слить данные с помощью ранее написанного алгоритма.

Посмотреть код

Решение

Python
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
    return True


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