Подтвердить что ты не робот

Обратить строку без использования reverse() или [:: - 1]?

Я наткнулся на странное упражнение Codecademy, которое потребовало функции, которая ввела бы строку в качестве ввода и вернула бы ее в обратном порядке. Единственная проблема заключалась в том, что вы не могли использовать обратный метод или общий ответ здесь в stackoverflow, [::-1].

Очевидно, что в реальном мире программирования наиболее вероятно использовать метод extended slice или даже использовать функцию reversed, но возможно, есть случаи, когда это не сработает?

Я представляю решение ниже в стиле Q & A, если оно полезно для людей в будущем.

4b9b3361

Ответ 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
Отсутствует