Показаны сообщения с ярлыком python. Показать все сообщения
Показаны сообщения с ярлыком python. Показать все сообщения

четверг, 6 ноября 2014 г.

внезапное открытие касательно list(), set(), tuple()

Бывает, что я использую одну и ту же конструкцию в python, и лишь спустя некоторое время открываю более красивый способ достичь того же самого. В данном случае речь идет о разбиении строки на символы. Раньше я использовал list comprehension вида
[c for c in mystring]

Оказывается, есть и более простой вариант:
list(mystring)

Соответственные варианты для кортежа и множества:
tuple(mystring), set(mystring)

пятница, 12 сентября 2014 г.

определяем "палиндромичность" строки в python 2.7

Рассмотрим основные варианты определения, является ли строка палиндромом, т.е. горизонтально симметричной относительно середины строкой.

Первый вариант, с использованием слайсов
def is_pali(s):
    return s==s[::-1]

Выражение s[::-1] возвращает новую строку, состоящую из символов данной строки, взятых в обратном порядке.

Второй вариант, с использованием функции (на самом деле, класса) reversed.
def is_pali(s):
    return s==''.join(reversed(s))

Так как reversed(s) возвращает итератор, для сравнения с оригинальной строкой необходимо собрать на его основе новую строку, для этого используется строковый метод join.

Третий вариант, также с использованием reversed.
def is_pali(s):
    return all(map(lambda x:x[0]==x[1],zip(s,reversed(s))))

Zip возвращает список кортежей длины 2, где первым элементом (индекс 0) является N-ный символ исходной строки, вторым (с индексом 1) - N-ный символ обращенной строки. В случае равенства между собой элементов каждого из кортежей строка является палиндромом.

И последний вариант, с использованием рекурсии. Сравниваем первый и последний символы строки. Если они различны, строка не является палиндромом. Если они одинаковы, строка может быть палиндромом, чтобы убедиться в этом, рекурсивно обрабатываем строку, полученную из текущей отбрасыванием первого и последнего символов. Базовый случай рекурсии: пустая строка и строка длиной в один символ являются палиндромами, возвращаем истинное значение.
def is_pali(s):
    if len(s)<=1:
        return True
    if s[0]==s[-1]:
        return is_pali(s[1:-1])
    else:
        return False

Перепишем, используя short-circuit evaluation (ленивое вычисление логических выражений c and и or).
Если длина строки меньше единицы, сразу возвращаем True. Здесь подойдет or:
def is_pali(s):
    return len(s)<=1 or ...

Далее, если первый и последний символы одинаковы, возвращаем значение, которое отдаст рекурсивный вызов, иначе, возвращаем ложное значение. Здесь напрашивается and:
def is_pali(s):
    return len(s)<=1 or s[0]==s[-1] and is_pali(s[1:-1])

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

понедельник, 18 августа 2014 г.

BurdoBordo как генерализация FizzBuzz

Многим известно  тестовое задание FizzBuzz. Возникла (а почему бы и нет?) идея решить более общую задачу. Будут заданы два делителя и две соответствующих им строки. Результатом будет вывод исходного числа или строки в зависимости от делимости числа. Наивный, понятный, хорошо поддерживаемый первый вариант:

def BurdoBordo(x,BURDO="BURDO",burdo=3,BORDO="BORDO",bordo=5):
    if x%burdo==0 and x%bordo==0:
        return BURDO+BORDO
    elif x%burdo==0:
        return BURDO
    elif x%bordo==0:
        return BORDO
    else:
        return str(x)
FizzBuzz=lambda x: BurdoBordo(x,BURDO="Fizz",burdo=3,BORDO="Buzz",bordo=5)
for x in xrange(1,101):
    print FizzBuzz(x)


Следующий вариант, в котором более активно используются особенности python.

def BurdoBordo(x,BURDO="BURDO",burdo=3,BORDO="BORDO",bordo=5):
    return ((BURDO,)+('',)*burdo)[x%burdo]+((BORDO,)+('',)*bordo)[x%bordo] or str(x)

FizzBuzz=lambda x: BurdoBordo(x,BURDO="Fizz",burdo=3,BORDO="Buzz",bordo=5)
for x in xrange(1,101):
    print FizzBuzz(x)

И, наконец, последний вариант, с индексами и short-circuit evaluation.

def BurdoBordo(x,BURDO="BURDO",burdo=3,BORDO="BORDO",bordo=5):
    return (BURDO+BORDO)[x%burdo and len(BURDO):x%bordo and len(BURDO) or len(BURDO+BORDO)] or str(x)

FizzBuzz=lambda x: BurdoBordo(x,BURDO="Fizz",burdo=3,BORDO="Buzz",bordo=5)
for x in xrange(1,101):
    print FizzBuzz(x)