Перевернуть строку в Python - PullRequest
1234 голосов
/ 31 мая 2009

Нет встроенной функции reverse для объекта Python str. Каков наилучший способ реализации этого метода?

Если вы предоставляете очень краткий ответ, пожалуйста, уточните его эффективность. Например, преобразован ли объект str в другой объект и т. Д.

Ответы [ 25 ]

2 голосов
/ 23 мая 2019

Существующие ответы верны только в том случае, если игнорируются модификаторы Unicode / кластеры графем. Я рассмотрю это позже, но сначала посмотрим на скорость некоторых алгоритмов разворота:

enter image description here

list_comprehension  : min:   0.6μs, mean:   0.6μs, max:    2.2μs
reverse_func        : min:   1.9μs, mean:   2.0μs, max:    7.9μs
reverse_reduce      : min:   5.7μs, mean:   5.9μs, max:   10.2μs
reverse_loop        : min:   3.0μs, mean:   3.1μs, max:    6.8μs

enter image description here

list_comprehension  : min:   4.2μs, mean:   4.5μs, max:   31.7μs
reverse_func        : min:  75.4μs, mean:  76.6μs, max:  109.5μs
reverse_reduce      : min: 749.2μs, mean: 882.4μs, max: 2310.4μs
reverse_loop        : min: 469.7μs, mean: 577.2μs, max: 1227.6μs

Вы можете видеть, что время для понимания списка (reversed = string[::-1]) во всех случаях намного меньше (даже после исправления моей опечатки).

Сторнирование строк

Если вы действительно хотите перевернуть строку в обычном смысле этого слова, это НАМНОГО сложнее. Например, возьмем следующую строку ( коричневый палец, указывающий влево , желтый палец, указывающий вверх ). Это две графемы, но три юникодных кода. Дополнительный модификатор кожи .

example = "???"

Но если вы измените его любым из указанных способов, вы получите коричневый палец, указывающий вверх , желтый палец, указывающий влево . Причина этого заключается в том, что «коричневый» модификатор цвета все еще находится в середине и применяется ко всему, что находится до него. Итак, у нас есть

  • U: палец направлен вверх
  • M: коричневый модификатор
  • L: указатель влево

и

original: LMU
reversed: UML (above solutions)
reversed: ULM (correct reversal)

Unicode Grapheme Clusters немного сложнее, чем просто кодовые точки модификатора. К счастью, есть библиотека для обработки графем :

>>> import grapheme
>>> g = grapheme.graphemes("???")
>>> list(g)
['??', '?']

и, следовательно, правильный ответ будет

def reverse_graphemes(string):
    g = list(grapheme.graphemes(string))
    return ''.join(g[::-1])

, который также является самым медленным:

list_comprehension  : min:    0.5μs, mean:    0.5μs, max:    2.1μs
reverse_func        : min:   68.9μs, mean:   70.3μs, max:  111.4μs
reverse_reduce      : min:  742.7μs, mean:  810.1μs, max: 1821.9μs
reverse_loop        : min:  513.7μs, mean:  552.6μs, max: 1125.8μs
reverse_graphemes   : min: 3882.4μs, mean: 4130.9μs, max: 6416.2μs

Код

#!/usr/bin/env python

import numpy as np
import random
import timeit
from functools import reduce
random.seed(0)


def main():
    longstring = ''.join(random.choices("ABCDEFGHIJKLM", k=2000))
    functions = [(list_comprehension, 'list_comprehension', longstring),
                 (reverse_func, 'reverse_func', longstring),
                 (reverse_reduce, 'reverse_reduce', longstring),
                 (reverse_loop, 'reverse_loop', longstring)
                 ]
    duration_list = {}
    for func, name, params in functions:
        durations = timeit.repeat(lambda: func(params), repeat=100, number=3)
        duration_list[name] = list(np.array(durations) * 1000)
        print('{func:<20}: '
              'min: {min:5.1f}μs, mean: {mean:5.1f}μs, max: {max:6.1f}μs'
              .format(func=name,
                      min=min(durations) * 10**6,
                      mean=np.mean(durations) * 10**6,
                      max=max(durations) * 10**6,
                      ))
        create_boxplot('Reversing a string of length {}'.format(len(longstring)),
                       duration_list)


def list_comprehension(string):
    return string[::-1]


def reverse_func(string):
    return ''.join(reversed(string))


def reverse_reduce(string):
    return reduce(lambda x, y: y + x, string)


def reverse_loop(string):
    reversed_str = ""
    for i in string:
        reversed_str = i + reversed_str
    return reversed_str


def create_boxplot(title, duration_list, showfliers=False):
    import seaborn as sns
    import matplotlib.pyplot as plt
    import operator
    plt.figure(num=None, figsize=(8, 4), dpi=300,
               facecolor='w', edgecolor='k')
    sns.set(style="whitegrid")
    sorted_keys, sorted_vals = zip(*sorted(duration_list.items(),
                                           key=operator.itemgetter(1)))
    flierprops = dict(markerfacecolor='0.75', markersize=1,
                      linestyle='none')
    ax = sns.boxplot(data=sorted_vals, width=.3, orient='h',
                     flierprops=flierprops,
                     showfliers=showfliers)
    ax.set(xlabel="Time in ms", ylabel="")
    plt.yticks(plt.yticks()[0], sorted_keys)
    ax.set_title(title)
    plt.tight_layout()
    plt.savefig("output-string.png")


if __name__ == '__main__':
    main()
1 голос
/ 28 октября 2018

Вот так:

def reverse_string(string):
    character_list = []
    for char in string:
        character_list.append(char)
    reversed_string = ""
    for char in reversed(character_list):
        reversed_string += char
    return reversed_string
1 голос
/ 16 апреля 2018

Все вышеперечисленные решения идеальны, но если мы пытаемся перевернуть строку, используя цикл for в python, это будет немного сложнее, поэтому вот как мы можем перевернуть строку, используя цикл for

string ="hello,world"
for i in range(-1,-len(string)-1,-1):
    print (string[i],end=(" ")) 

Надеюсь, это кому-нибудь пригодится.

1 голос
/ 13 января 2018

Рекурсивный метод:

def reverse(s): return s[0] if len(s)==1 else s[len(s)-1] + reverse(s[0:len(s)-1])

пример:

print(reverse("Hello!"))    #!olleH
1 голос
/ 04 мая 2015

Вот это не модно:

def reverse(text):
    r_text = ''
    index = len(text) - 1

    while index >= 0:
        r_text += text[index] #string canbe concatenated
        index -= 1

    return r_text

print reverse("hello, world!")
0 голосов
/ 10 декабря 2018
def reverse_string(string):
    length = len(string)
    temp = ''
    for i in range(length):
        temp += string[length - i - 1]
    return temp

print(reverse_string('foo')) #prints "oof"

Это работает путем циклического перебора строки и присвоения ее значений в обратном порядке другой строке.

0 голосов
/ 02 сентября 2018

Это простая и значимая обратная функция, легкая для понимания и кодирования

def reverse_sentence(text):
    words = text.split(" ")
    reverse =""
    for word in reversed(words):
        reverse += word+ " "
    return reverse
0 голосов
/ 13 января 2018

s = 'Hello world'

s [:: - 1]

в приведенном выше примере метка s или переменная s содержит строку, содержащую строку Hello world, а на втором шаге я печатаю обратную строку Hello world, беря начиная со всего и все в обратном порядке с -1.

0 голосов
/ 24 марта 2016
s = 'hello'
ln = len(s)
i = 1
while True:
    rev = s[ln-i]
    print rev,
    i = i + 1
    if i == ln + 1 :
        break

ВЫХОД:

o l l e h
0 голосов
/ 03 февраля 2016

Конечно, в Python вы можете делать очень интересные вещи в 1 строку. :)
Вот простое, универсальное решение, которое может работать на любом языке программирования.

def reverse_string(phrase):
    reversed = ""
    length = len(phrase)
    for i in range(length):
        reversed += phrase[length-1-i]
    return reversed

phrase = raw_input("Provide a string: ")
print reverse_string(phrase)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...