etc./StackOverFlow

Python에서 문자열 반전

청렴결백한 만능 재주꾼 2022. 3. 4. 07:55
반응형

질문자 :oneself


Python의 str 객체에는 내장된 reverse 이 방법을 구현하는 가장 좋은 방법은 무엇입니까?

매우 간결한 답변을 제공하는 경우 효율성에 대해 자세히 설명하십시오. 예를 들어 str 개체가 다른 개체로 변환되는지 여부 등



어때요:

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

이것은 확장 슬라이스 구문입니다. [begin:end:step] 을 수행하여 작동합니다. 시작과 끝을 종료하고 단계를 -1로 지정하면 문자열이 반전됩니다.


Paolo Bergantino

@Paolo의 s[::-1] 이 가장 빠릅니다. 더 느린 접근 방식(더 읽기 쉽지만 논쟁의 여지가 있음)은 ''.join(reversed(s)) 입니다.


Alex Martelli

문자열에 대해 역함수를 구현하는 가장 좋은 방법은 무엇입니까?

이 질문에 대한 제 경험은 학문적입니다. 그러나 빠른 답변을 찾고 있는 전문가라면 -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'

더 긴 설명

학술 박람회에 관심이 있으시면 계속 읽으십시오.

파이썬의 str 객체에는 내장된 역함수가 없습니다.

다음은 Python의 문자열에 대해 알아야 할 몇 가지 사항입니다.

  1. Python에서 문자열은 변경할 수 없습니다 . 문자열을 변경해도 문자열은 수정되지 않습니다. 새로운 것을 생성합니다.

  2. 문자열은 슬라이스 가능합니다. 문자열을 슬라이싱하면 문자열의 한 지점에서 지정된 증분만큼 앞뒤로 새 문자열을 얻을 수 있습니다. 그들은 슬라이스 표기법 또는 아래 첨자에서 슬라이스 객체를 사용합니다.

     string[subscript]

아래 첨자는 중괄호 안에 콜론을 포함하여 슬라이스를 만듭니다.

 string[start:stop:step]

중괄호 외부에 슬라이스를 생성하려면 슬라이스 객체를 생성해야 합니다.

 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]

그러나 조각이나 원본 작성자의 의도에 익숙하지 않은 사람이 이것을 더 읽기 쉽고 이해하기 쉽게 만들 수 있는 방법은 무엇입니까? 아래 첨자 표기법 밖에서 슬라이스 객체를 만들고 설명적인 이름을 지정한 다음 아래 첨자 표기법에 전달해 보겠습니다.

 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은 문자열 연결을 최적화하지만 다른 구현에서는 다음을 수행하지 않을 수 있습니다.

... a += b 또는 a = a + b 형식의 명령문에 대한 CPython의 효율적인 제자리 문자열 연결 구현에 의존하지 마십시오. 이 최적화는 CPython에서도 취약하며(일부 유형에서만 작동함) refcounting을 사용하지 않는 구현에서는 전혀 존재하지 않습니다. 라이브러리의 성능에 민감한 부분에서는 ''.join() 형식을 대신 사용해야 합니다. 이렇게 하면 다양한 구현에서 선형 시간에 연결이 발생합니다.


Aaron Hall

빠른 답변(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()가 아닌가요?

문제

  • 문맥
    • 파이썬 2.x
    • 파이썬 3.x
  • 대본:
    • 개발자가 문자열을 변환하려고 합니다.
    • 변환은 모든 문자의 순서를 반대로 하는 것입니다.

해결책

함정

  • string.reverse() 와 같은 것을 기대할 수 있습니다.
  • 기본 관용구(일명 " 파이썬 ") 솔루션은 새로운 개발자가 읽을 수 없습니다.
  • 개발자는 슬라이스 표기법을 피하기 위해 string.reverse() 버전을 구현하려는 유혹을 받을 수 있습니다.
  • 슬라이스 표기법의 출력은 경우에 따라 직관적이지 않을 수 있습니다.
    • 예를 들어 example02를 참조하십시오.
      • print 'coup_ate_grouping'[-4:] ## => 'ping'
      • 에 비해
      • print 'coup_ate_grouping'[-4:-1] ## => 'pin'
      • 에 비해
      • print 'coup_ate_grouping'[-1] ## => 'g'
    • [-1] 에 대한 인덱싱의 다른 결과는 일부 개발자를 실망시킬 수 있습니다.

이론적 해석

파이썬에는 알아야 할 특별한 상황이 있습니다. 문자열은 반복 가능한 유형입니다.

string.reverse() 메서드를 제외하는 한 가지 이유는 파이썬 개발자에게 이 특별한 상황의 힘을 활용하도록 동기를 부여하는 것입니다.

간단히 말해서, 이것은 단순히 문자열의 각 개별 문자가 다른 프로그래밍 언어의 배열과 마찬가지로 요소의 순차적 배열의 일부로 쉽게 조작될 수 있음을 의미합니다.

이것이 어떻게 작동하는지 이해하기 위해 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에서 슬라이스 표기법이 작동하는 방식을 이해하는 것과 관련된 인지 부하 는 실제로 언어 학습에 많은 시간을 투자하고 싶지 않은 일부 채택자와 개발자에게 너무 많을 수 있습니다.

그럼에도 불구하고 일단 기본 원칙을 이해하고 나면 고정된 문자열 조작 방법에 비해 이 접근 방식이 훨씬 유리할 수 있습니다.

다르게 생각하는 사람들을 위해 람다 함수, 반복자 또는 간단한 일회성 함수 선언과 같은 대체 접근 방식이 있습니다.

원하는 경우 개발자는 자신의 string.reverse() 메서드를 구현할 수 있지만 Python의 이러한 측면에 대한 근거를 이해하는 것이 좋습니다.

또한보십시오


dreftymac

이 답변은 조금 더 길고 3개의 섹션이 있습니다. 기존 솔루션의 벤치마크 , 여기에서 대부분의 솔루션이 잘못된 이유 , 내 솔루션 .

기존 답변은 Unicode Modifiers/grapheme 클러스터가 무시되는 경우에만 정확합니다. 나중에 다루겠지만 먼저 일부 반전 알고리즘의 속도를 살펴보겠습니다.

여기에 이미지 설명 입력

 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] )이 모든 경우에 가장 낮음을 알 수 있습니다(오타를 수정한 후에도).

문자열 반전

상식적으로 문자열을 뒤집고 싶다면 훨씬 더 복잡합니다. 예를 들어 다음 문자열을 사용합니다( 왼쪽을 가리키는 갈색 손가락, 위쪽을 가리키는 노란색 손가락 ). 그것들은 2개의 자소이지만 3개의 유니코드 코드 포인트입니다. 추가 항목은 스킨 수정자 입니다.

 example = ""

그러나 주어진 방법 중 하나를 사용하여 반대로 하면갈색 손가락이 위쪽을 가리키고 노란색 손가락이 왼쪽을 가리킵니다 . 그 이유는 "갈색" 색상 수정자가 여전히 중간에 있고 그 이전에 무엇이든 적용되기 때문입니다. 그래서 우리는

  • U: 위로 가리키는 손가락
  • M: 갈색 수식어
  • L: 왼쪽을 가리키는 손가락

그리고

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

유니코드 문자소 클러스터 는 수정자 코드 포인트보다 조금 더 복잡합니다. 운 좋게도 자소 를 처리하기 위한 라이브러리가 있습니다.

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

Martin Thoma

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

Harry

덜 당혹스러운 방법은 다음과 같습니다.

 string = 'happy' print(string)

'행복하다'

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

'이파'

영어로 [-1::-1]은 다음과 같습니다.

"-1에서 시작하여 -1 단계로 끝까지 이동합니다."


pX0r

reversed() 또는 [::-1]을 사용하지 않고 파이썬에서 문자열을 뒤집습니다.

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

akshaynagpal

이것은 또한 흥미로운 방법입니다:

 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()를 지원하는 bytearray를 사용하는 또 다른 '이국적인' 방법

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

생산할 것입니다:

 '!siht esreveR'

gxpr

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

Javier

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"

이것은 문자열을 반복하고 그 값을 다른 문자열에 역순으로 할당하여 작동합니다.


Pika the Master of the Whales

original = "string" rev_index = original[::-1] rev_func = list(reversed(list(original))) #nsfw print(original) print(rev_index) print(''.join(rev_func))

JEX

면접을 위한 프로그래밍 방식으로 이를 해결하기 위해

 def reverse_a_string(string: str) -> str: """ This method is used to reverse a string. Args: string: a string to reverse Returns: a reversed string """ if type(string) != str: raise TypeError("{0} This not a string, Please provide a string!".format(type(string))) string_place_holder = "" start = 0 end = len(string) - 1 if end >= 1: while start <= end: string_place_holder = string_place_holder + string[end] end -= 1 return string_place_holder else: return string a = "hello world" rev = reverse_a_string(a) print(rev)

산출:

 dlrow olleh

Soumya

 a=input() print(a[::-1])

위의 코드는 사용자로부터 입력을 받고 [::-1]을 추가하여 입력의 반대와 동일한 출력을 출력합니다.

산출:

 >>> Happy >>> yppaH

그러나 문장의 경우 아래 코드 출력을 보십시오.

 >>> Have a happy day >>> yad yppah a evaH

그러나 문자열의 순서가 아닌 문자열의 문자만 반전시키려면 다음을 시도하십시오.

 a=input().split() #Splits the input on the basis of space (" ") for b in a: #declares that var (b) is any value in the list (a) print(b[::-1], end=" ") #End declares to print the character in its quotes (" ") without a new line.

위의 코드 2번에서 ** 변수 b는 목록(a)의 모든 값입니다.** 입력에서 split을 사용하면 입력의 변수가 목록이 되기 때문에 var a를 목록이라고 말했습니다. . 또한 int(input())의 경우 split을 사용할 수 없음을 기억하십시오.

산출:

 >>> Have a happy day >>> evaH a yppah yad

위의 코드 에 end(" ") 를 추가하지 않으면 다음과 같이 인쇄됩니다.

 >>> Have a happy day >>> evaH >>> a >>> yppah >>> yad

다음은 end()를 이해하는 예입니다.

암호:

 for i in range(1,6): print(i) #Without end()

산출:

 >>> 1 >>> 2 >>> 3 >>> 4 >>> 5

이제 end()로 코드를 작성하십시오.

 for i in range(1,6): print(i, end=" || ")

산출:

 >>> 1 || 2 || 3 || 4 || 5 ||

Code Carbonate

다음은 멋진 것이 아닙니다.

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

an offer can't refuse

다음은 [::-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() 이 더 빠릅니다.


Claudiu Creanga

재귀적 방법:

 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

matt

위의 모든 솔루션은 완벽하지만 파이썬에서 for 루프를 사용하여 문자열을 반전시키려고 하면 약간 까다로워질 것이므로 for 루프를 사용하여 문자열을 반전시키는 방법은 다음과 같습니다.

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

나는 이것이 누군가에게 도움이되기를 바랍니다.


nitin

문자열을 뒤집는 방법에는 여러 가지가 있지만 재미를 위해 다른 방법도 만들었습니다. 나는 이 접근법이 그렇게 나쁘지 않다고 생각한다.

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

Ehsan Ahmadi

아니면 다음과 같이 할 수 있습니까?

 >>> a = 'hello world' >>> ''.join(a[len(a) - i - 1] for i in range(len(a))) 'dlrow olleh' >>>

생성기 표현식 및 문자열 인덱싱 사용.


U12-Forward

물론, 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)

olga

s = 'hello' ln = len(s) i = 1 while True: rev = s[ln-i] print rev, i = i + 1 if i == ln + 1 : break

출력:

 olleh

sudistack

전체 목록과 함께 반전된 기능을 사용할 수 있습니다. 그러나이 방법이 python 3에서 제거되고 불필요하게 된 이유를 이해하지 못합니다.

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

alejandro izquierdo

출처 : http:www.stackoverflow.com/questions/931092/reverse-a-string-in-python

반응형