首页 文章

在Python中反转一个字符串

提问于
浏览
1152

Python的 str 对象没有内置的 reverse 函数 . 实现此方法的最佳方法是什么?

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

21 回答

  • -5
    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"
    

    这通过循环遍历字符串并以相反的顺序将其值分配给另一个字符串来工作 .

  • -1

    这是一个没有 [::-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() 更快 .

  • 183

    递归方法:

    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
    
  • 0

    怎么样:

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

    这是extended slice语法 . 它的工作原理是 [begin:end:step] - 通过离开开始和结束并指定步长为-1,它会反转一个字符串 .

  • 2355

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

  • 232

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

    我对这个问题的经验是学术性的 . 但是,如果您是专业人士正在寻找快速答案,请使用步骤为 -1 的切片:

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

    或更可读(但由于方法名称查找速度较慢,并且在给定迭代器时连接形成列表的事实), 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字符串:

    • 在Python中, strings are immutable . 更改字符串不会修改字符串 . 它创造了一个新的 .

    • 字符串是可切片的 . 切片字符串会以给定的增量从字符串中的一个点(向后或向前)向另一个点提供一个新字符串 . 它们在下标中采用切片表示法或切片对象:

    string[subscript]
    

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

    string[start:stop:step]
    

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

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

    一种可读的方法:

    虽然 ''.join(reversed('foo')) 是可读的,但它需要在另一个被调用函数上调用字符串方法 str.join ,这可能相当慢 . 让's put this in a function - we'回到它:

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

    最高效的方法:

    使用反向切片要快得多:

    'foo'[::-1]
    

    但是,对于不太熟悉切片或原作者意图的人,我们怎样才能使其更具可读性和易懂性?让我们在下标表示法之外创建一个切片对象,给它一个描述性名称,并将其传递给下标符号 .

    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
    

    这在理论上是不好的,因为,请记住, strings are immutable - 所以每次看起来你在你的 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优化字符串连接,而其他实现may not

    ...不要依赖CPython为a = b或a = a b形式的语句高效实现就地字符串连接 . 即使在CPython中,这种优化也很脆弱(它只适用于某些类型),并且在不使用引用计数的实现中根本不存在 . 在库的性能敏感部分中,应使用'.join()形式 . 这将确保在各种实现中以线性时间进行连接 .

  • 1

    快速回答(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提出的解决方案让我感到震惊,但是在阅读第一条评论时我感到恐惧的后座:“这是非常pythonic . 干得好!”我很不安,这样一个聪明的社区认为使用这种神秘的方法来做一些基本的东西是一个好主意 . 为什么不是s.reverse()?

    问题

    • Context

    • Python 2.x.

    • Python 3.x

    • Scenario:

    • Developer想要转换字符串

    • 转换是颠倒所有字符的顺序

    解决方案

    陷阱

    • 开发人员可能会期待像 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有一个特殊情况需要注意:字符串是iterable类型 .

    排除 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中如何工作相关的cognitive load对于那些不希望花费太多时间学习语言的采用者和开发者来说确实太过分了 .

    然而,一旦理解了基本原理,这种方法相对于固定字符串操作方法的能力就会非常有利 .

    对于那些不这么认为的人,有其他方法,例如lambda函数,迭代器或简单的一次性函数声明 .

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

    另见

  • -2

    看待它的一个较小的令人困惑的方式是:

    string = 'happy'
    print(string)
    

    '快乐'

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

    'yppah'

    英文[-1 :: - 1]读作:

    “从-1开始,一路走,步长为-1”

  • 3

    使用切片表示法

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

    使用reverse()函数

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

    使用递归

    def rev_string(s): 
        if len(s) == 1:
            return s
    
        return s[-1] + rev_string(s[:-1])
    
  • 4

    在不使用reverse()或[:: - 1]的情况下在python中反转字符串

    def reverse(test):
        n = len(test)
        x=""
        for i in range(n-1,-1,-1):
            x += test[i]
        return x
    
  • 0
    def reverse(input):
        return reduce(lambda x,y : y+x, input)
    
  • 0

    这也是一个有趣的方式:

    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 = byterarray('Reverse this!', 'UTF-8')
    b.reverse()
    b.decode('UTF-8')`
    

    将产生:

    '!siht esreveR'
    
  • 10

    这是一个不花哨的:

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

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

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

    我希望这个对某人有帮助 .

  • -4

    这是我的风格:

    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

    这里很简单:

    打印“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

  • -4

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

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

    s ='Hello world'

    S [:: - 1]

    在上面的示例中,标签s或变量s是包含Hello世界字符串的保持字符串,在第二步中,通过以反向步骤顺序从-1开始,以-1开始打印Hello世界字符串的反向 .

  • 1

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

    您可以使用带有列表复合的反转功能 . 但是我不明白为什么这个方法在python 3中被淘汰了,这是不必要的 .

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

相关问题