반복문이 리스트의 항목을 제대로 삭제하지 못합니다.


아래의 코드는 모든 모음 알파벳(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)
  • 2016년 08월 01일에 작성됨

조회수 77


1 답변


좋아요
0
싫어요
채택취소하기

반복문이 진행됨에 따라 리스트가 수정되면서 생기는 문제입니다. 아래의 코드와 같이 리스트의 복사본을 만들어 순회 중인 리스트에서 값을 제거하지 않도록 해보세요.

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')
  • 2016년 08월 02일에 작성됨

로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close