Обратить строку без использования reverse() или [:: - 1]?
Я наткнулся на странное упражнение Codecademy, которое потребовало функции, которая ввела бы строку в качестве ввода и вернула бы ее в обратном порядке. Единственная проблема заключалась в том, что вы не могли использовать обратный метод или общий ответ здесь в stackoverflow, [::-1]
.
Очевидно, что в реальном мире программирования наиболее вероятно использовать метод extended slice или даже использовать функцию reversed
, но возможно, есть случаи, когда это не сработает?
Я представляю решение ниже в стиле Q & A, если оно полезно для людей в будущем.
Ответы
Ответ 1
Вы также можете сделать это с рекурсией:
def reverse(text):
if len(text) <= 1:
return text
return reverse(text[1:]) + text[0]
И простой пример для строки hello
:
reverse(hello)
= reverse(ello) + h # The recursive step
= reverse(llo) + e + h
= reverse(lo) + l + e + h
= reverse(o) + l + l + e + h # Base case
= o + l + l + e + h
= olleh
Ответ 2
Еще один вариант:
from collections import deque
def reverse(iterable):
d = deque()
d.extendleft(iterable)
return ''.join(d)
Ответ 3
Используйте обратный range
:
def reverse(strs):
for i in xrange(len(strs)-1, -1, -1):
yield strs[i]
...
>>> ''.join(reverse('hello'))
'olleh'
xrange
или range
с -1 шагом будут возвращать элементы в обратном порядке, поэтому нам нужно выполнить итерацию с len(string)-1
до -1
(исключение) и выборку элементов из строки один за другим.
>>> list(xrange(len(strs) -1, -1 , -1))
[4, 3, 2, 1, 0] #iterate over these indexes and fetch the items from the string
Однострочник:
def reverse(strs):
return ''.join([strs[i] for i in xrange(len(strs)-1, -1, -1)])
...
>>> reverse('hello')
'olleh'
Ответ 4
ИЗМЕНИТЬ
Недавняя активность по этому вопросу заставила меня оглянуться назад и изменить свое решение на быстрый однострочный с помощью генератора:
rev = ''.join([text[len(text) - count] for count in xrange(1,len(text)+1)])
Хотя, очевидно, здесь есть несколько лучших ответов, например, отрицательный шаг в диапазоне или функция xrange. Следующее - мое оригинальное решение:
Вот мое решение, я объясню его шаг за шагом.
def reverse(text):
lst = []
count = 1
for i in range(0,len(text)):
lst.append(text[len(text)-count])
count += 1
lst = ''.join(lst)
return lst
print reverse('hello')
Сначала мы должны передать параметр функции, в данном случае text
.
Затем я устанавливаю пустой список с именем lst
для использования позже. (На самом деле я не знал, что мне нужен список, пока я не доберусь до цикла for
, вы увидите, почему это необходимо за секунду.)
Переменная count
будет иметь смысл, как только я войду в цикл for
Итак, давайте взглянем на базовую версию того, что мы пытаемся выполнить:
Имеет смысл, что добавление последнего символа в список приведет к обратному порядку. Например:
>>lst = []
>>word = 'foo'
>>lst.append(word[2])
>>print lst
['o']
Но для продолжения изменения порядка нам нужно добавить word[1]
, а затем word[0]
:
>>lst.append(word[2])
>>lst.append(word[1])
>>lst.append(word[0])
>>print lst
['o','o','f']
Это здорово, теперь у нас есть список, который имеет исходное слово в обратном порядке, и его можно преобразовать обратно в строку с помощью .join()
. Но есть проблема. Это работает для слова foo, оно даже работает для любого слова длиной 3 символа. Но как насчет слова с 5 символами? Или 10 символов? Теперь это не сработает. Что делать, если бы мы могли динамически изменять индекс, который мы добавляем, чтобы любое слово было возвращено в обратном порядке?
Введите для цикла.
for i in range(0,len(text)):
lst.append(text[len(text)-count])
count += 1
Прежде всего, нужно использовать in range()
, а не только in
, потому что нам нужно перебирать символы в слове, но нам также нужно потянуть индексное значение слова, чтобы мы изменили заказ.
Первая часть тела цикла for должна выглядеть знакомой. Его очень похоже на
>>lst.append(word[..index..])
На самом деле базовая концепция его точно такая же:
>>lst.append(text[..index..])
Так что же все в середине дела?
Ну, нам нужно сначала добавить индекс последней буквы в наш список, который является длиной слова, text
, -1. Отныне мы будем называть его l (t) -1
>>lst.append(text[len(text)-1])
Это будет всегда получать последнюю букву нашего слова и добавлять ее к lst
, независимо от длины слова. Но теперь, когда у нас есть последняя буква, которая равна l (t) - 1, нам нужна вторая - последняя буква, которая является l (t) - 2 и т.д., Пока не будет добавлено больше символов для добавления в список, Помните нашу переменную count
сверху? Это пригодится. Используя цикл for
, мы можем увеличивать значение count
на 1 на каждую итерацию, так что вычитаемое нами значение увеличивается, пока цикл for не повторится по всему слову:
>>for i in range(0,len(text)):
..
.. lst.append(text[len(text)-count])
.. count += 1
Теперь, когда у нас есть сердце нашей функции, давайте посмотрим, что у нас есть до сих пор:
def reverse(text):
lst = []
count = 1
for i in range(0,len(text)):
lst.append(text[len(text)-count])
count += 1
Мы почти закончили! Прямо сейчас, если бы мы назвали нашу функцию словом "hello", мы получили бы список, который выглядит так:
[ 'о', 'L', 'L', 'е', 'ч']
Нам не нужен список, мы хотим строку. Для этого мы можем использовать .join
:
def reverse(text):
lst = []
count = 1
for i in range(0,len(text)):
lst.append(text[len(text)-count])
count += 1
lst = ''.join(lst) # join the letters together without a space
return lst
И что это. Если мы назовем слово "hello" на reverse(), мы получим следующее:
>>print reverse('hello')
olleh
Очевидно, что это больше кода, чем необходимо в реальной жизненной ситуации. Использование перевернутой функции или расширенного среза было бы оптимальным способом выполнения этой задачи, но, возможно, есть какой-то пример, когда это не сработает, и вам понадобится это. В любом случае, я решил, что поделюсь им для всех, кто будет заинтересован.
Если у вас есть другие идеи, я бы хотел их услышать!
Ответ 5
Только кодирование Python на несколько дней, но я чувствую, что это было довольно чистое решение. Создайте пустой список, зациклируйте каждую букву в строке и добавьте ее в начало списка, верните объединенный список в виде строки.
def reverse(text):
backwardstext = []
for letter in text:
backwardstext.insert(0, letter)
return ''.join(backwardstext)
Ответ 6
Вдохновленный Джоном, ответьте, как насчет этого
word = 'hello'
q = deque(word)
''.join(q.pop() for _ in range(len(word)))
Ответ 7
Это очень интересный вопрос, я хотел бы предложить простой
Ответ гильберта:
>>> S='abcdefg'
>>> ''.join(item[1] for item in sorted(enumerate(S), reverse=True))
'gfedcba'
Краткое объяснение:
enumerate()
возвращает [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g')]
. Индексы и значения.
Чтобы изменить значения, просто измените его на sorted()
.
Наконец, просто верните его обратно в str
Ответ 8
Я использовал это:
def reverse(text):
s=""
l=len(text)
for i in range(l):
s+=text[l-1-i]
return s
Ответ 9
Я создал разные версии того, как изменить строку в python в моем репо:
https://github.com/fedmich/Python-Codes/tree/master/Reverse%20a%20String
Вы можете сделать это, используя метод list-assrehension или лямбда-метод:
# Reverse a string without using reverse() function
s = 'Federico';
li = list( s ) #convert string to list
ret = [ li[i-1] for i in xrange(len(li),0,-1) ] #1 liner lambda
print ( "".join( ret ) )
или выполнив обратную для цикла
# Reverse a string without using reverse() function
s = 'Federico';
r = []
length = len(s)
for i in xrange(length,0,-1):
r.append( s[ i - 1] )
print ( "".join(r) )
Ответ 10
reduce(lambda x, y : y + x, "hello world")
Ответ 11
Игра в гольф: r=lambda x:"".join(x[i] for i in range(len(x-1),-1,-1))
.
Ответ 12
Я просто решил это в академии кода и проверял мои ответы и просматривал этот список. поэтому с очень ограниченным пониманием python я просто сделал это, и он сработал, чтобы работать.
def reverse(s):
i = len(s) - 1
sNew = ''
while i >= 0:
sNew = sNew + str(s[i])
i = i -1
return sNew
Ответ 13
def reverse(s):
return "".join(s[i] for i in range(len(s)-1, -1, -1))
Ответ 14
Ответ Blender прекрасен, но для очень длинной строки это приведет к колоссальному RuntimeError: maximum recursion depth exceeded
. Можно реорганизовать один и тот же код в цикл while, как часто приходится делать с рекурсией в python. Очевидно, что все еще плохо из-за проблем времени и памяти, но по крайней мере не будет ошибок.
def reverse(text):
answer = ""
while text:
answer = text[0] + answer
text = text[1:]
return answer
Ответ 15
Сегодня мне было задано такое же упражнение на ручке и бумаге, поэтому я придумал эту функцию для списков:
def rev(s):
l = len(s)
for i,j in zip(range(l-1, 0, -1), range(l//2)):
s[i], s[j] = s[j], s[i]
return s
который может использоваться со строками с "".join(rev(list("hello")))
Ответ 16
Это способ сделать это с помощью цикла while:
def reverse(s):
t = -1
s2 = ''
while abs(t) < len(s) + 1:
s2 = s2 + s[t]
t = t - 1
return s2
Ответ 17
Я также просто решил своеобразное упражнение по кодакадемии и хотел сравнить мой подход с другими. Я не нашел решение, которое я использовал до сих пор, поэтому я подумал, что я зарегистрируюсь здесь и предоставляю свое решение другим. И, возможно, я получаю предложение или полезный комментарий о том, как улучшить код.
Хорошо, вот оно, я не использовал список для хранения строки, вместо этого я просто получил доступ к строковому индексу. Мне сначала потребовалось заняться len() и номером индекса, но в итоге это сработало:).
def reverse(x):
reversestring = ""
for n in range(len(str(x))-1,-1, -1):
reversestring += x[n]
return reversestring
Мне все еще интересно, можно ли решить проблему reversestring = ""
более элегантным способом, или даже если это "плохой стиль", но пока я не нашел ответа.
Ответ 18
def reverse(text):
a=""
l=len(text)
while(l>=1):
a+=text[l-1]
l-=1
return a
я просто конкатенировал строку a с наивысшими индексами текста (которая продолжает уменьшаться на 1 каждый цикл).
Ответ 19
Все, что я сделал для создания обратной строки, использует функцию xrange
с длиной строки в цикле for и шаг назад в следующем:
myString = "ABC"
for index in xrange(len(myString),-1):
print index
Мой вывод - "CBA"
Ответ 20
Вы можете просто изменить итерацию строки, начиная с последнего символа. С помощью python вы можете использовать представление списка для построения списка символов в обратном порядке, а затем присоединиться к ним, чтобы получить обратную строку в одном слое:
def reverse(s):
return "".join([s[-i-1] for i in xrange(len(s))])
если вам не разрешено даже использовать отрицательную индексацию, вы должны заменить s[-i-1]
на s[len(s)-i-1]
Ответ 21
Вы получили много альтернативных ответов, но просто добавили еще одно простое решение - первое, что пришло в голову примерно так:
def reverse(text):
reversed_text = ""
for n in range(len(text)):
reversed_text += text[-1 - n]
return reversed_text
Это не так быстро, как некоторые из других опций, о которых люди упоминали (или встроенные методы), но их легко отслеживать, поскольку мы просто используем длину строки text
для конкатенации одного символа за раз, от конца к фронту.
Ответ 22
def reverseThatString(theString):
reversedString = ""
lenOfString = len(theString)
for i,j in enumerate(theString):
lenOfString -= 1
reversedString += theString[lenOfString]
return reversedString
Ответ 23
Это мое решение, использующее for я в цикле диапазона:
def reverse(string):
tmp = ""
for i in range(1,len(string)+1):
tmp += string[len(string)-i]
return tmp
Это довольно легко понять. Я начинаю с 1, чтобы избежать ограничения индекса.
Ответ 24
Вы можете просто сделать это
def rev(str):
rev = ""
for i in range(0,len(str)):
rev = rev + str[(len(str)-1)-i]
return rev
Ответ 25
Здесь мой вклад:
def rev(test):
test = list(test)
i = len(test)-1
result = []
print test
while i >= 0:
result.append(test.pop(i))
i -= 1
return "".join(result)
Ответ 26
у вас есть достаточно ответа.
Просто хочу поделиться другим способом.
вы можете написать две небольшие функции для обратного и сравнить выход функции с заданной строкой
var = ''
def reverse (data):
for i in data:
var = i + var
return var
если не var == data:
напечатать "Без палиндрома"
else:
напечатать "Palindrome"
Ответ 27
Не очень умное, но сложное решение
def reverse(t):
for j in range(len(t) // 2):
t = t[:j] + t[- j - 1] + t[j + 1:- j - 1] + t[j] + t[len(t) - j:]
return t
Ответ 28
Pointfree:
from functools import partial
from operator import add
flip = lambda f: lambda x, y: f(y, x)
rev = partial(reduce, flip(add))
Тест:
>>> rev('hello')
'olleh'
Ответ 29
Как я могу думать без использования встроенных функций:
a = 'word'
count = 0
for letter in a:
count += 1
b = ''
for letter in a:
b += a[count-1]
count -= 1
И если вы напечатаете b:
print b
drow
Ответ 30
Мое решение:
s = raw_input ( "Enter string" )
печать
def reverse (текст):
st = ""
rev = ""
count = len(text)
print "Lenght of text: ", len(text)
print
for c in range(len(text)):
count = count - 1
st = st + "".join(text[c])
rev = rev + "".join(text[count])
print "count: ", count
print "print c: ", c
print "text[c]: ", text[c]
print
print "Original: ", st
print "Reversed: ", rev
return rev
обратный (ы)
Экран результатов
Введите строку joca
Длина текста: 4
count: 3
print c: 0
текст [c]: j
count: 2
print c: 1
текст [c]: o
count: 1
печать c: 2
текст [c]: c
count: 0
print c: 3
текст [c]: a
Оригинал: joca
Обратный: acoj
Отсутствует