Python의 str
객체에는 내장된 reverse
이 방법을 구현하는 가장 좋은 방법은 무엇입니까?
매우 간결한 답변을 제공하는 경우 효율성에 대해 자세히 설명하십시오. 예를 들어 str
개체가 다른 개체로 변환되는지 여부 등
질문자 :oneself
Python의 str
객체에는 내장된 reverse
이 방법을 구현하는 가장 좋은 방법은 무엇입니까?
매우 간결한 답변을 제공하는 경우 효율성에 대해 자세히 설명하십시오. 예를 들어 str
개체가 다른 개체로 변환되는지 여부 등
어때요:
>>> 'hello world'[::-1] 'dlrow olleh'
이것은 확장 슬라이스 구문입니다. [begin:end:step]
을 수행하여 작동합니다. 시작과 끝을 종료하고 단계를 -1로 지정하면 문자열이 반전됩니다.
@Paolo의 s[::-1]
이 가장 빠릅니다. 더 느린 접근 방식(더 읽기 쉽지만 논쟁의 여지가 있음)은 ''.join(reversed(s))
입니다.
문자열에 대해 역함수를 구현하는 가장 좋은 방법은 무엇입니까?
이 질문에 대한 제 경험은 학문적입니다. 그러나 빠른 답변을 찾고 있는 전문가라면 -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의 문자열에 대해 알아야 할 몇 가지 사항입니다.
Python에서 문자열은 변경할 수 없습니다 . 문자열을 변경해도 문자열은 수정되지 않습니다. 새로운 것을 생성합니다.
문자열은 슬라이스 가능합니다. 문자열을 슬라이싱하면 문자열의 한 지점에서 지정된 증분만큼 앞뒤로 새 문자열을 얻을 수 있습니다. 그들은 슬라이스 표기법 또는 아래 첨자에서 슬라이스 객체를 사용합니다.
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() 형식을 대신 사용해야 합니다. 이렇게 하면 다양한 구현에서 선형 시간에 연결이 발생합니다.
### 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()가 아닌가요?
string.reverse()
와 같은 것을 기대할 수 있습니다.string.reverse()
버전을 구현하려는 유혹을 받을 수 있습니다.print 'coup_ate_grouping'[-4:] ## => 'ping'
print 'coup_ate_grouping'[-4:-1] ## => 'pin'
print 'coup_ate_grouping'[-1] ## => 'g'
[-1]
에 대한 인덱싱의 다른 결과는 일부 개발자를 실망시킬 수 있습니다.파이썬에는 알아야 할 특별한 상황이 있습니다. 문자열은 반복 가능한 유형입니다.
string.reverse()
메서드를 제외하는 한 가지 이유는 파이썬 개발자에게 이 특별한 상황의 힘을 활용하도록 동기를 부여하는 것입니다.
간단히 말해서, 이것은 단순히 문자열의 각 개별 문자가 다른 프로그래밍 언어의 배열과 마찬가지로 요소의 순차적 배열의 일부로 쉽게 조작될 수 있음을 의미합니다.
이것이 어떻게 작동하는지 이해하기 위해 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'
Python에서 슬라이스 표기법이 작동하는 방식을 이해하는 것과 관련된 인지 부하 는 실제로 언어 학습에 많은 시간을 투자하고 싶지 않은 일부 채택자와 개발자에게 너무 많을 수 있습니다.
그럼에도 불구하고 일단 기본 원칙을 이해하고 나면 고정된 문자열 조작 방법에 비해 이 접근 방식이 훨씬 유리할 수 있습니다.
다르게 생각하는 사람들을 위해 람다 함수, 반복자 또는 간단한 일회성 함수 선언과 같은 대체 접근 방식이 있습니다.
원하는 경우 개발자는 자신의 string.reverse() 메서드를 구현할 수 있지만 Python의 이러한 측면에 대한 근거를 이해하는 것이 좋습니다.
이 답변은 조금 더 길고 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 = ""
그러나 주어진 방법 중 하나를 사용하여 반대로 하면갈색 손가락이 위쪽을 가리키고 노란색 손가락이 왼쪽을 가리킵니다 . 그 이유는 "갈색" 색상 수정자가 여전히 중간에 있고 그 이전에 무엇이든 적용되기 때문입니다. 그래서 우리는
그리고
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()
def rev_string(s): return s[::-1]
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])
덜 당혹스러운 방법은 다음과 같습니다.
string = 'happy' print(string)
'행복하다'
string_reversed = string[-1::-1] print(string_reversed)
'이파'
영어로 [-1::-1]은 다음과 같습니다.
"-1에서 시작하여 -1 단계로 끝까지 이동합니다."
reversed() 또는 [::-1]을 사용하지 않고 파이썬에서 문자열을 뒤집습니다.
def reverse(test): n = len(test) x="" for i in range(n-1,-1,-1): x += test[i] return x
이것은 또한 흥미로운 방법입니다:
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'
def reverse(input): return reduce(lambda x,y : y+x, input)
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"
이것은 문자열을 반복하고 그 값을 다른 문자열에 역순으로 할당하여 작동합니다.
original = "string" rev_index = original[::-1] rev_func = list(reversed(list(original))) #nsfw print(original) print(rev_index) print(''.join(rev_func))
면접을 위한 프로그래밍 방식으로 이를 해결하기 위해
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
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 ||
다음은 멋진 것이 아닙니다.
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!")
다음은 [::-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()
이 더 빠릅니다.
재귀적 방법:
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
위의 모든 솔루션은 완벽하지만 파이썬에서 for 루프를 사용하여 문자열을 반전시키려고 하면 약간 까다로워질 것이므로 for 루프를 사용하여 문자열을 반전시키는 방법은 다음과 같습니다.
string ="hello,world" for i in range(-1,-len(string)-1,-1): print (string[i],end=(" "))
나는 이것이 누군가에게 도움이되기를 바랍니다.
문자열을 뒤집는 방법에는 여러 가지가 있지만 재미를 위해 다른 방법도 만들었습니다. 나는 이 접근법이 그렇게 나쁘지 않다고 생각한다.
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"))
아니면 다음과 같이 할 수 있습니까?
>>> a = 'hello world' >>> ''.join(a[len(a) - i - 1] for i in range(len(a))) 'dlrow olleh' >>>
생성기 표현식 및 문자열 인덱싱 사용.
물론, 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)
s = 'hello' ln = len(s) i = 1 while True: rev = s[ln-i] print rev, i = i + 1 if i == ln + 1 : break
출력:
olleh
전체 목록과 함께 반전된 기능을 사용할 수 있습니다. 그러나이 방법이 python 3에서 제거되고 불필요하게 된 이유를 이해하지 못합니다.
string = [ char for char in reversed(string)]
출처 : http:www.stackoverflow.com/questions/931092/reverse-a-string-in-python
JSON 파일을 예쁘게 인쇄하는 방법은 무엇입니까? (0) | 2022.03.04 |
---|---|
Python에서 정수를 문자열로 변환 (0) | 2022.03.04 |
Android 애플리케이션에서 활동 간에 데이터를 어떻게 전달합니까? (0) | 2022.03.04 |
객체 배열에서 속성 값을 배열로 추출 (0) | 2022.02.27 |
Python에서 유형을 확인하는 표준 방법은 무엇입니까? (0) | 2022.02.27 |