반복문이 리스트의 항목을 제대로 삭제하지 못합니다.
조회수 5116회
아래의 코드는 모든 모음 알파벳(aeiouAEIOU)을 문자열에서 제거해주는 함수 anti_vowel입니다. 제대로 동작할 거라 기대했는데, "Hey look Words!" 라는 샘플값을 입력값으로 주면 "Hy lk Words!"라고 반환됩니다. 즉, 마지막 'o'를 삭제하지 못하고 있는데, 왜 이러는 걸까요?
text = "Hey look Words!"
def anti_vowel(text):
textlist = list(text)
for char in textlist:
if char.lower() in 'aeiou':
textlist.remove(char)
return "".join(textlist)
print anti_vowel(text)
1 답변
-
반복문이 진행됨에 따라 리스트가 수정되면서 생기는 문제입니다. 아래의 코드와 같이 리스트의 복사본을 만들어 순회 중인 리스트에서 값을 제거하지 않도록 해보세요.
for char in textlist[:]: #shallow copy of the list # etc
좀더 명확하게 현재 문제를 파악해보고 싶으시다면
print char, textlist
를 반복문의 시작부분에 삽입해보세요. 아마 리스트 좌측에 원본 문자열이 수직으로 나올거라 생각하셨겠지만, 사실 출력되는 값은 아래와 같습니다 :H ['H', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] e ['H', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] ['H', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] # ! l ['H', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] o ['H', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] k ['H', 'y', ' ', 'l', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] # Problem!! ['H', 'y', ' ', 'l', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] W ['H', 'y', ' ', 'l', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] o ['H', 'y', ' ', 'l', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] d ['H', 'y', ' ', 'l', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] s ['H', 'y', ' ', 'l', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] ! ['H', 'y', ' ', 'l', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] Hy lk Words!
왜 이러는걸까요? 파이썬의
for x in y
형태의 반복문은 사실 겉보기에 좀더 직관적으로 보일 뿐, 사실 일반적인 반복문처럼 리스트의 각 요소들을 인덱스로 순회합니다. 즉, 리스트를 순회하면서 리스트의 요소들을 제거하다보면, (위에 보이는 바와 같이) 스킵하고 지나가는 값들이 생기는 거죠. 이는 결국"look"
의 두번째o
를 놓치고 지나가는 결과를 만듭니다. 왜냐하면 이전 문자를 삭제하면서 두번째o
의 인덱스가 한칸 당겨지면서 이미 순회한 인덱스가 되기 때문입니다. 그 후에,"Words"
의o
를 찾게 되면, 문자열의 가장 첫번째o
, 즉, 놓치고 지나간o
를 삭제하게 되는 것이죠.
만들고자 하시는 코드는 아래와 같이 더 좋은 (더 깔끔한) 방법으로 작성하실 수 있습니다.
def remove_vowels(text): # function names should start with verbs! :) return ''.join(ch for ch in text if ch.lower() not in 'aeiou')
댓글 입력