反转Python中的字符串

问题:反转Python中的字符串

reversePython str对象没有内置函数。实施此方法的最佳方法是什么?

如果提供非常简洁的答案,请详细说明其效率。例如,是否将str对象转换为其他对象等。

There is no built in reverse function for Python’s str object. What is the best way of implementing this method?

If supplying a very concise answer, please elaborate on its efficiency. For example, whether the str object is converted to a different object, etc.


回答 0

怎么样:

>>> 'hello world'[::-1]
'dlrow olleh'

这是扩展片语法。它的工作方式是[begin:end:step]-离开begin和end并指定步骤-1,它反转字符串。

How about:

>>> 'hello world'[::-1]
'dlrow olleh'

This is extended slice syntax. It works by doing [begin:end:step] – by leaving begin and end off and specifying a step of -1, it reverses a string.


回答 1

@Paolo s[::-1]是最快的;较慢的方法(可能更具可读性,但这值得商))是''.join(reversed(s))

@Paolo’s s[::-1] is fastest; a slower approach (maybe more readable, but that’s debatable) is ''.join(reversed(s)).


回答 2

为字符串实现反向函数的最佳方法是什么?

我对这个问题的经验是学术上的。但是,如果您是专业人士在寻找快速答案,请使用按-1以下步骤操作的切片:

>>> 'a string'[::-1]
'gnirts a'

或更可读(但由于方法名称查找和在给定迭代器时join形成列表的事实而变慢)str.join

>>> ''.join(reversed('a string'))
'gnirts a'

或为了可读性和可重用性,将切片放入函数中

def reversed_string(a_string):
    return a_string[::-1]

然后:

>>> reversed_string('a_string')
'gnirts_a'

更长的解释

如果您对学术博览会感兴趣,请继续阅读。

Python的str对象中没有内置的反向函数。

您应该了解以下有关Python字符串的几件事:

  1. 在Python中,字符串是不可变的。更改字符串不会修改该字符串。它创建了一个新的。

  2. 字符串是可切片的。分割字符串会以给定的增量从字符串的一个点向后或向前,再到另一点,为您提供一个新的字符串。它们在下标中采用切片符号或切片对象:

    string[subscript]

下标通过在括号内包含冒号来创建切片:

    string[start:stop:step]

要在大括号之外创建切片,您需要创建一个slice对象:

    slice_obj = slice(start, stop, step)
    string[slice_obj]

可读的方法:

虽然''.join(reversed('foo'))可读,但需要str.join在另一个调用的函数上调用字符串方法,这可能会比较慢。让我们将其放在函数中-我们将回到它:

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

最高效的方法:

使用反向切片快得多:

'foo'[::-1]

但是,对于不熟悉切片或原始作者意图的人,我们如何使它更具可读性和可理解性?让我们在下标符号之外创建一个slice对象,为其指定一个描述性名称,然后将其传递给下标符号。

start = stop = None
step = -1
reverse_slice = slice(start, stop, step)
'foo'[reverse_slice]

实现为功能

为了实际实现此功能,我认为在语义上足够清晰,只需使用一个描述性名称即可:

def reversed_string(a_string):
    return a_string[::-1]

用法很简单:

reversed_string('foo')

您的老师可能想要什么:

如果您有一位讲师,他们可能希望您从一个空字符串开始,然后从旧字符串开始构建一个新字符串。您可以使用while循环使用纯语法和文字进行此操作:

def reverse_a_string_slowly(a_string):
    new_string = ''
    index = len(a_string)
    while index:
        index -= 1                    # index = index - 1
        new_string += a_string[index] # new_string = new_string + character
    return new_string

从理论上讲这是不好的,因为请记住,字符串是不可变的 -因此,每次看起来像在您的字符上附加一个字符时new_string,理论上每次都会创建一个新的字符串!但是,CPython知道如何在某些情况下对此进行优化,其中这种微不足道的情况就是其中之一。

最佳实践

从理论上讲,更好的方法是将您的子字符串收集到列表中,然后再加入它们:

def reverse_a_string_more_slowly(a_string):
    new_strings = []
    index = len(a_string)
    while index:
        index -= 1                       
        new_strings.append(a_string[index])
    return ''.join(new_strings)

但是,正如我们在下面的CPython时序中所看到的,实际上这需要花费更长的时间,因为CPython可以优化字符串连接。

时机

计时如下:

>>> a_string = 'amanaplanacanalpanama' * 10
>>> min(timeit.repeat(lambda: reverse_string_readable_answer(a_string)))
10.38789987564087
>>> min(timeit.repeat(lambda: reversed_string(a_string)))
0.6622700691223145
>>> min(timeit.repeat(lambda: reverse_a_string_slowly(a_string)))
25.756799936294556
>>> min(timeit.repeat(lambda: reverse_a_string_more_slowly(a_string)))
38.73570013046265

CPython优化了字符串连接,而其他实现可能没有

…不依赖于CPython对a + = b或a = a + b形式的语句的就地字符串连接的有效实现。即使在CPython中,这种优化也是脆弱的(仅适用于某些类型),并且在不使用引用计数的实现中根本没有这种优化。在库的性能敏感部分中,应使用”.join()形式。这将确保在各种实现方式中串联发生在线性时间内。

What is the best way of implementing a reverse function for strings?

My own experience with this question is academic. However, if you’re a pro looking for the quick answer, use a slice that steps by -1:

>>> 'a string'[::-1]
'gnirts a'

or more readably (but slower due to the method name lookups and the fact that join forms a list when given an iterator), str.join:

>>> ''.join(reversed('a string'))
'gnirts a'

or for readability and reusability, put the slice in a function

def reversed_string(a_string):
    return a_string[::-1]

and then:

>>> reversed_string('a_string')
'gnirts_a'

Longer explanation

If you’re interested in the academic exposition, please keep reading.

There is no built-in reverse function in Python’s str object.

Here is a couple of things about Python’s strings you should know:

  1. In Python, strings are immutable. Changing a string does not modify the string. It creates a new one.

  2. Strings are sliceable. Slicing a string gives you a new string from one point in the string, backwards or forwards, to another point, by given increments. They take slice notation or a slice object in a subscript:

    string[subscript]
    

The subscript creates a slice by including a colon within the braces:

    string[start:stop:step]

To create a slice outside of the braces, you’ll need to create a slice object:

    slice_obj = slice(start, stop, step)
    string[slice_obj]

A readable approach:

While ''.join(reversed('foo')) is readable, it requires calling a string method, str.join, on another called function, which can be rather relatively slow. Let’s put this in a function – we’ll come back to it:

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

Most performant approach:

Much faster is using a reverse slice:

'foo'[::-1]

But how can we make this more readable and understandable to someone less familiar with slices or the intent of the original author? Let’s create a slice object outside of the subscript notation, give it a descriptive name, and pass it to the subscript notation.

start = stop = None
step = -1
reverse_slice = slice(start, stop, step)
'foo'[reverse_slice]

Implement as Function

To actually implement this as a function, I think it is semantically clear enough to simply use a descriptive name:

def reversed_string(a_string):
    return a_string[::-1]

And usage is simply:

reversed_string('foo')

What your teacher probably wants:

If you have an instructor, they probably want you to start with an empty string, and build up a new string from the old one. You can do this with pure syntax and literals using a while loop:

def reverse_a_string_slowly(a_string):
    new_string = ''
    index = len(a_string)
    while index:
        index -= 1                    # index = index - 1
        new_string += a_string[index] # new_string = new_string + character
    return new_string

This is theoretically bad because, remember, strings are immutable – so every time where it looks like you’re appending a character onto your new_string, it’s theoretically creating a new string every time! However, CPython knows how to optimize this in certain cases, of which this trivial case is one.

Best Practice

Theoretically better is to collect your substrings in a list, and join them later:

def reverse_a_string_more_slowly(a_string):
    new_strings = []
    index = len(a_string)
    while index:
        index -= 1                       
        new_strings.append(a_string[index])
    return ''.join(new_strings)

However, as we will see in the timings below for CPython, this actually takes longer, because CPython can optimize the string concatenation.

Timings

Here are the timings:

>>> a_string = 'amanaplanacanalpanama' * 10
>>> min(timeit.repeat(lambda: reverse_string_readable_answer(a_string)))
10.38789987564087
>>> min(timeit.repeat(lambda: reversed_string(a_string)))
0.6622700691223145
>>> min(timeit.repeat(lambda: reverse_a_string_slowly(a_string)))
25.756799936294556
>>> min(timeit.repeat(lambda: reverse_a_string_more_slowly(a_string)))
38.73570013046265

CPython optimizes string concatenation, whereas other implementations may not:

… do not rely on CPython’s efficient implementation of in-place string concatenation for statements in the form a += b or a = a + b . This optimization is fragile even in CPython (it only works for some types) and isn’t present at all in implementations that don’t use refcounting. In performance sensitive parts of the library, the ”.join() form should be used instead. This will ensure that concatenation occurs in linear time across various implementations.


回答 3

快速解答(TL; DR)

### example01 -------------------
mystring  =   'coup_ate_grouping'
backwards =   mystring[::-1]
print backwards

### ... or even ...
mystring  =   'coup_ate_grouping'[::-1]
print mystring

### result01 -------------------
'''
gnipuorg_eta_puoc
'''

详细答案

背景

提供此答案是为了解决@odigity的以下问题:

哇。起初,我对Paolo提出的解决方案感到震惊,但这使我在读了第一条评论时感到的恐惧退缩了:“那太好了。做得好!” 我感到非常不安,以至于这样一个聪明的社区认为将如此神秘的方法用于如此基本的东西是一个好主意。为什么不只是s.reverse()?

问题

  • 语境
    • Python 2.x
    • Python 3.x
  • 场景:
    • 开发人员想要转换字符串
    • 转换是颠倒所有字符的顺序

陷阱

  • 开发人员可能期望像 string.reverse()
  • 较新的开发人员可能无法阅读本机惯用的(又称“ pythonic ”)解决方案
  • 开发人员可能会尝试实施自己的版本,string.reverse()以避免切片符号。
  • 在某些情况下,切片符号的输出可能是违反直觉的:
    • 参见例如example02
      • print 'coup_ate_grouping'[-4:] ## => 'ping'
      • 相比
      • print 'coup_ate_grouping'[-4:-1] ## => 'pin'
      • 相比
      • print 'coup_ate_grouping'[-1] ## => 'g'
    • 建立索引的不同结果[-1]可能会使一些开发人员失望

基本原理

Python有一种特殊的情况要注意:字符串是可迭代的类型。

排除string.reverse()方法的一个基本原理是给予python开发人员动力以利用这种特殊情况的力量。

简而言之,这简单地意味着字符串中的每个单独字符都可以像其他编程语言中的数组一样容易地作为元素顺序排列的一部分进行操作。

要了解其工作原理,请查看example02可以提供很好的概述。

示例02

### example02 -------------------
## start (with positive integers)
print 'coup_ate_grouping'[0]  ## => 'c'
print 'coup_ate_grouping'[1]  ## => 'o' 
print 'coup_ate_grouping'[2]  ## => 'u' 

## start (with negative integers)
print 'coup_ate_grouping'[-1]  ## => 'g'
print 'coup_ate_grouping'[-2]  ## => 'n' 
print 'coup_ate_grouping'[-3]  ## => 'i' 

## start:end 
print 'coup_ate_grouping'[0:4]    ## => 'coup'    
print 'coup_ate_grouping'[4:8]    ## => '_ate'    
print 'coup_ate_grouping'[8:12]   ## => '_gro'    

## start:end 
print 'coup_ate_grouping'[-4:]    ## => 'ping' (counter-intuitive)
print 'coup_ate_grouping'[-4:-1]  ## => 'pin'
print 'coup_ate_grouping'[-4:-2]  ## => 'pi'
print 'coup_ate_grouping'[-4:-3]  ## => 'p'
print 'coup_ate_grouping'[-4:-4]  ## => ''
print 'coup_ate_grouping'[0:-1]   ## => 'coup_ate_groupin'
print 'coup_ate_grouping'[0:]     ## => 'coup_ate_grouping' (counter-intuitive)

## start:end:step (or start:end:stride)
print 'coup_ate_grouping'[-1::1]  ## => 'g'   
print 'coup_ate_grouping'[-1::-1] ## => 'gnipuorg_eta_puoc'

## combinations
print 'coup_ate_grouping'[-1::-1][-4:] ## => 'puoc'

结论

对于某些不希望在学习语言上花费很多时间的采用者和开发人员来说,与理解切片符号在python中的工作方式相关的认知负担确实可能过大。

但是,一旦理解了基本原理,此方法相对于固定字符串操作方法的功能可能会非常有利。

对于那些有其他想法的人,还有其他方法,例如lambda函数,迭代器或简单的一次性函数声明。

如果需要,开发人员可以实现自己的string.reverse()方法,但是最好理解python这方面的原理。

也可以看看

Quick Answer (TL;DR)

Example

### example01 -------------------
mystring  =   'coup_ate_grouping'
backwards =   mystring[::-1]
print backwards

### ... or even ...
mystring  =   'coup_ate_grouping'[::-1]
print mystring

### result01 -------------------
'''
gnipuorg_eta_puoc
'''

Detailed Answer

Background

This answer is provided to address the following concern from @odigity:

Wow. I was horrified at first by the solution Paolo proposed, but that took a back seat to the horror I felt upon reading the first comment: “That’s very pythonic. Good job!” I’m so disturbed that such a bright community thinks using such cryptic methods for something so basic is a good idea. Why isn’t it just s.reverse()?

Problem

  • Context
    • Python 2.x
    • Python 3.x
  • Scenario:
    • Developer wants to transform a string
    • Transformation is to reverse order of all the characters

Solution

Pitfalls

  • Developer might expect something like string.reverse()
  • The native idiomatic (aka “pythonic“) solution may not be readable to newer developers
  • Developer may be tempted to implement his or her own version of string.reverse() to avoid slice notation.
  • The output of slice notation may be counter-intuitive in some cases:
    • see e.g., example02
      • print 'coup_ate_grouping'[-4:] ## => 'ping'
      • compared to
      • print 'coup_ate_grouping'[-4:-1] ## => 'pin'
      • compared to
      • print 'coup_ate_grouping'[-1] ## => 'g'
    • the different outcomes of indexing on [-1] may throw some developers off

Rationale

Python has a special circumstance to be aware of: a string is an iterable type.

One rationale for excluding a string.reverse() method is to give python developers incentive to leverage the power of this special circumstance.

In simplified terms, this simply means each individual character in a string can be easily operated on as a part of a sequential arrangement of elements, just like arrays in other programming languages.

To understand how this works, reviewing example02 can provide a good overview.

Example02

### example02 -------------------
## start (with positive integers)
print 'coup_ate_grouping'[0]  ## => 'c'
print 'coup_ate_grouping'[1]  ## => 'o' 
print 'coup_ate_grouping'[2]  ## => 'u' 

## start (with negative integers)
print 'coup_ate_grouping'[-1]  ## => 'g'
print 'coup_ate_grouping'[-2]  ## => 'n' 
print 'coup_ate_grouping'[-3]  ## => 'i' 

## start:end 
print 'coup_ate_grouping'[0:4]    ## => 'coup'    
print 'coup_ate_grouping'[4:8]    ## => '_ate'    
print 'coup_ate_grouping'[8:12]   ## => '_gro'    

## start:end 
print 'coup_ate_grouping'[-4:]    ## => 'ping' (counter-intuitive)
print 'coup_ate_grouping'[-4:-1]  ## => 'pin'
print 'coup_ate_grouping'[-4:-2]  ## => 'pi'
print 'coup_ate_grouping'[-4:-3]  ## => 'p'
print 'coup_ate_grouping'[-4:-4]  ## => ''
print 'coup_ate_grouping'[0:-1]   ## => 'coup_ate_groupin'
print 'coup_ate_grouping'[0:]     ## => 'coup_ate_grouping' (counter-intuitive)

## start:end:step (or start:end:stride)
print 'coup_ate_grouping'[-1::1]  ## => 'g'   
print 'coup_ate_grouping'[-1::-1] ## => 'gnipuorg_eta_puoc'

## combinations
print 'coup_ate_grouping'[-1::-1][-4:] ## => 'puoc'

Conclusion

The cognitive load associated with understanding how slice notation works in python may indeed be too much for some adopters and developers who do not wish to invest much time in learning the language.

Nevertheless, once the basic principles are understood, the power of this approach over fixed string manipulation methods can be quite favorable.

For those who think otherwise, there are alternate approaches, such as lambda functions, iterators, or simple one-off function declarations.

If desired, a developer can implement her own string.reverse() method, however it is good to understand the rationale behind this aspect of python.

See also


回答 4

仅当忽略Unicode修饰符/字形群集时,现有答案才是正确的。我将在稍后处理,但首先请看一些反转算法的速度:

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

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])的时间在所有情况下都是最低的(即使在修正我的错字之后)。

字符串反转

如果您真的想按常识反转字符串,则方法会更加复杂。例如,采用以下字符串(棕色手指指向左黄色手指指向上)。那是两个字素,但有3个unicode码点。另一个是皮肤修饰剂

example = "👈🏾👆"

但是,如果使用任何给定的方法将其反转,则会使棕色手指指向上方黄色手指指向左侧。这样做的原因是“棕色”颜色修改器仍在中间,并应用于之前的任何内容。所以我们有

  • U:手指向上
  • M:棕色修饰剂
  • L:手指指向左

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

Unicode音素簇比修饰符代码点要复杂一些。幸运的是,用于处理库字形

>>> 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()

The existing answers are only correct if Unicode Modifiers / grapheme clusters are ignored. I’ll deal with that later, but first have a look at the speed of some reversal algorithms:

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

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

You can see that the time for the list comprehension (reversed = string[::-1]) is in all cases by far the lowest (even after fixing my typo).

String Reversal

If you really want to reverse a string in the common sense, it is WAY more complicated. For example, take the following string (brown finger pointing left, yellow finger pointing up). Those are two graphemes, but 3 unicode code points. The additional one is a skin modifier.

example = "👈🏾👆"

But if you reverse it with any of the given methods, you get brown finger pointing up, yellow finger pointing left. The reason for this is that the “brown” color modifier is still in the middle and gets applied to whatever is before it. So we have

  • U: finger pointing up
  • M: brown modifier
  • L: finger pointing left

and

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

Unicode Grapheme Clusters are a bit more complicated than just modifier code points. Luckily, there is a library for handling graphemes:

>>> import grapheme
>>> g = grapheme.graphemes("👈🏾👆")
>>> list(g)
['👈🏾', '👆']

and hence the correct answer would be

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

which also is by far the slowest:

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

The Code

#!/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()

回答 5

1.使用切片符号

def rev_string(s): 
    return s[::-1]

2.使用reversed()函数

def rev_string(s): 
    return ''.join(reversed(s))

3.使用递归

def rev_string(s): 
    if len(s) == 1:
        return s

    return s[-1] + rev_string(s[:-1])

1. using slice notation

def rev_string(s): 
    return s[::-1]

2. using reversed() function

def rev_string(s): 
    return ''.join(reversed(s))

3. using recursion

def rev_string(s): 
    if len(s) == 1:
        return s

    return s[-1] + rev_string(s[:-1])

回答 6

观察它的一种比较简单的方法是:

string = 'happy'
print(string)

‘快乐’

string_reversed = string[-1::-1]
print(string_reversed)

‘yppah’

用英语[-1 ::-1]读为:

“从-1开始,一直走,采取-1的步骤”

A lesser perplexing way to look at it would be:

string = 'happy'
print(string)

‘happy’

string_reversed = string[-1::-1]
print(string_reversed)

‘yppah’

In English [-1::-1] reads as:

“Starting at -1, go all the way, taking steps of -1”


回答 7

不使用reversed()或[::-1]反转python中的字符串

def reverse(test):
    n = len(test)
    x=""
    for i in range(n-1,-1,-1):
        x += test[i]
    return x

Reverse a string in python without using reversed() or [::-1]

def reverse(test):
    n = len(test)
    x=""
    for i in range(n-1,-1,-1):
        x += test[i]
    return x

回答 8

这也是一种有趣的方式:

def reverse_words_1(s):
    rev = ''
    for i in range(len(s)):
        j = ~i  # equivalent to j = -(i + 1)
        rev += s[j]
    return rev

或类似:

def reverse_words_2(s):
    rev = ''
    for i in reversed(range(len(s)):
        rev += s[i]
    return rev

使用支持.reverse()的BYTERArray的另一种“异国情调”方式

b = bytearray('Reverse this!', 'UTF-8')
b.reverse()
b.decode('UTF-8')

将生成:

'!siht esreveR'

This is also an interesting way:

def reverse_words_1(s):
    rev = ''
    for i in range(len(s)):
        j = ~i  # equivalent to j = -(i + 1)
        rev += s[j]
    return rev

or similar:

def reverse_words_2(s):
    rev = ''
    for i in reversed(range(len(s)):
        rev += s[i]
    return rev

Another more ‘exotic’ way using byterarray which supports .reverse()

b = bytearray('Reverse this!', 'UTF-8')
b.reverse()
b.decode('UTF-8')

will produce:

'!siht esreveR'

回答 9

def reverse(input):
    return reduce(lambda x,y : y+x, input)
def reverse(input):
    return reduce(lambda x,y : y+x, input)

回答 10

original = "string"

rev_index = original[::-1]
rev_func = list(reversed(list(original))) #nsfw

print(original)
print(rev_index)
print(''.join(rev_func))
original = "string"

rev_index = original[::-1]
rev_func = list(reversed(list(original))) #nsfw

print(original)
print(rev_index)
print(''.join(rev_func))

回答 11

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"

这是通过遍历一个字符串并将其值反向分配给另一个字符串来实现的。

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"

This works by looping through a string and assigning its values in reverse order to another string.


回答 12

这是一个没有幻想的:

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!")

Here is a no fancy one:

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!")

回答 13

这是一个没有[::-1]reversed(出于学习目的)的:

def reverse(text):
    new_string = []
    n = len(text)
    while (n > 0):
        new_string.append(text[n-1])
        n -= 1
    return ''.join(new_string)
print reverse("abcd")

您可以+=用来连接字符串,但join()速度更快。

Here is one without [::-1] or reversed (for learning purposes):

def reverse(text):
    new_string = []
    n = len(text)
    while (n > 0):
        new_string.append(text[n-1])
        n -= 1
    return ''.join(new_string)
print reverse("abcd")

you can use += to concatenate strings but join() is faster.


回答 14

递归方法:

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

Recursive method:

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

example:

print(reverse("Hello!"))    #!olleH

回答 15

以上所有解决方案都是完美的,但是如果我们尝试在python中使用for循环来反转字符串会变得有些棘手,所以这是我们如何使用for循环来反转字符串

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

我希望这对某人有帮助。

All of the above solutions are perfect but if we are trying to reverse a string using for loop in python will became a little bit tricky so here is how we can reverse a string using for loop

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

I hope this one will be helpful for someone.


回答 16

这是我的风格:

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

Thats my way:

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

回答 17

反向字符串有很多方法,但我也创建了另一种方法只是为了好玩。我认为这种方法还不错。

def reverse(_str):
    list_char = list(_str) # Create a hypothetical list. because string is immutable

    for i in range(len(list_char)/2): # just t(n/2) to reverse a big string
        list_char[i], list_char[-i - 1] = list_char[-i - 1], list_char[i]

    return ''.join(list_char)

print(reverse("Ehsan"))

There are a lot of ways to reverse a string but I also created another one just for fun. I think this approach is not that bad.

def reverse(_str):
    list_char = list(_str) # Create a hypothetical list. because string is immutable

    for i in range(len(list_char)/2): # just t(n/2) to reverse a big string
        list_char[i], list_char[-i - 1] = list_char[-i - 1], list_char[i]

    return ''.join(list_char)

print(reverse("Ehsan"))

回答 18

此类使用python魔术函数反转字符串:

class Reverse(object):
    """ Builds a reverse method using magic methods """

    def __init__(self, data):
        self.data = data
        self.index = len(data)


    def __iter__(self):
        return self

    def __next__(self):
        if self.index == 0:
            raise StopIteration

        self.index = self.index - 1
        return self.data[self.index]


REV_INSTANCE = Reverse('hello world')

iter(REV_INSTANCE)

rev_str = ''
for char in REV_INSTANCE:
    rev_str += char

print(rev_str)  

输出量

dlrow olleh

参考

This class uses python magic functions to reverse a string:

class Reverse(object):
    """ Builds a reverse method using magic methods """

    def __init__(self, data):
        self.data = data
        self.index = len(data)


    def __iter__(self):
        return self

    def __next__(self):
        if self.index == 0:
            raise StopIteration

        self.index = self.index - 1
        return self.data[self.index]


REV_INSTANCE = Reverse('hello world')

iter(REV_INSTANCE)

rev_str = ''
for char in REV_INSTANCE:
    rev_str += char

print(rev_str)  

Output

dlrow olleh

Reference


回答 19

使用python 3,您可以就地反转字符串,这意味着它不会被分配给另一个变量。首先,您必须将字符串转换为列表,然后利用该reverse()函数。

https://docs.python.org/3/tutorial/datastructures.html

   def main():
        my_string = ["h","e","l","l","o"]
        print(reverseString(my_string))

    def reverseString(s):
      print(s)
      s.reverse()
      return s

    if __name__ == "__main__":
        main()

With python 3 you can reverse the string in-place meaning it won’t get assigned to another variable. First you have to convert the string into a list and then leverage the reverse() function.

https://docs.python.org/3/tutorial/datastructures.html

   def main():
        my_string = ["h","e","l","l","o"]
        print(reverseString(my_string))

    def reverseString(s):
      print(s)
      s.reverse()
      return s

    if __name__ == "__main__":
        main()

回答 20

这是简单而有意义的反向功能,易于理解和编码

def reverse_sentence(text):
    words = text.split(" ")
    reverse =""
    for word in reversed(words):
        reverse += word+ " "
    return reverse

This is simple and meaningful reverse function, easy to understand and code

def reverse_sentence(text):
    words = text.split(" ")
    reverse =""
    for word in reversed(words):
        reverse += word+ " "
    return reverse

回答 21

这很简单:

打印“ loremipsum” [-1 ::-1]

从逻辑上讲:

def str_reverse_fun():
    empty_list = []
    new_str = 'loremipsum'
    index = len(new_str)
    while index:
        index = index - 1
        empty_list.append(new_str[index])
    return ''.join(empty_list)
print str_reverse_fun()

输出:

muspimerol

Here is simply:

print “loremipsum”[-1::-1]

and some logically:

def str_reverse_fun():
    empty_list = []
    new_str = 'loremipsum'
    index = len(new_str)
    while index:
        index = index - 1
        empty_list.append(new_str[index])
    return ''.join(empty_list)
print str_reverse_fun()

output:

muspimerol


回答 22

反转没有python魔术的字符串。

>>> def reversest(st):
    a=len(st)-1
    for i in st:
        print(st[a],end="")
        a=a-1

Reverse a string without python magic.

>>> def reversest(st):
    a=len(st)-1
    for i in st:
        print(st[a],end="")
        a=a-1

回答 23

当然,在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)

Sure, in Python you can do very fancy 1-line stuff. :)
Here’s a simple, all rounder solution that could work in any programming language.

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)

回答 24

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
s = 'hello'
ln = len(s)
i = 1
while True:
    rev = s[ln-i]
    print rev,
    i = i + 1
    if i == ln + 1 :
        break

OUTPUT :

o l l e h

回答 25

您可以将反向功能与列表综合一起使用。但是我不明白为什么在python 3中取消了这种方法是不必要的。

string = [ char for char in reversed(string)]

You can use the reversed function with a list comprehesive. But I don’t understand why this method was eliminated in python 3, was unnecessarily.

string = [ char for char in reversed(string)]