2011-01-12 1 views
2

최근에 /usr/share/dict/words을 순환하고 내 ispalindrome(x) 방법을 사용하여 회문 목록을 반환하는 방법을 작성했습니다. 여기에 코드가 있습니다 ... 무엇이 잘못 되었나요? 그것은 단지 10 분 동안 포장 마차 다음파이썬과 회문

 
def reverse(a): 
    return a[::-1] 

def ispalindrome(a): 
    b = reverse(a) 
    if b.lower() == a.lower(): 
     return True 
    else: 
     return False 

wl = open('/usr/share/dict/words', 'r') 
wordlist = wl.readlines() 
wl.close() 
for x in wordlist: 
    if not ispalindrome(x): 
     wordlist.remove(x) 
print wordlist 
+2

'ispalindrome = lambda a : a [:: - 1] .lower() == a.lower()'라는 짧은 인라인 정의는 ~ 25 %의 시간을 절약 해줍니다. – eumiro

+4

문제와 관련이 없지만 두 번째 함수를'return (reverse (a) .lower() == a.lower())'로 줄일 수 있습니다. '=='는 이미'True' 또는'False'를 리턴 할 것이므로'if' 문을 감쌀 필요는 없습니다. –

답변

5
wordlist = wl.readlines() 

는, 마지막에 새 줄 문자가있다, 그래서 당신의 목록과 같다 :의

['eye\n','bye\n', 'cyc\n'] 

요소가 분명히 회문 없습니다.

['eye','bye', 'cyc'] 

그래서 strip 개행 문자가 그것을 잘해야합니다

당신이 필요합니다. 목록 반복하며 문제를 일으키는의을 수정 :

wordlist = [line.strip() for line in open('/usr/share/dict/words')] 

편집 :

한 줄에서이 작업을 수행합니다. Matthew으로 지적 된 목록 이해력을 사용하십시오.

1

당신은 /usr/share/dict/words에서 각 단어의 끝에 줄 바꿈을 포함하고있는 파일의 모든 단어의 목록을 반환합니다. 그 말은 결코 당신이 어떤 palindromes도 찾지 못한다는 것을 의미합니다. 팔린 드롬을 발견했을 때 팔린 드롬을 기록하는 경우 목록에서 비 궁체 글씨를 지우는 대신 일기를 빠르게하면됩니다. 이 작업을 수행 할 때

+0

이것은 사실이지만 인쇄하는 이유에 대해서는 설명하지 않습니다. –

+0

@ 존스, 원래 코드를 읽어보십시오. * non * -palindromes를 제거하려고 시도합니다. 그리고 그것은 절반을 제거합니다. iterating하는 동안 수정으로 인해 모두 제거 할 수 없습니다. –

+0

당신 말이 맞아요. 그에 따라 내 대답을 업데이트했습니다. – Johnsyweb

3

두 가지 문제가 있다고 생각합니다.

첫째, 모든 단어를 목록으로 읽는 요지는 무엇입니까? 왜 각 단어를 차례로 처리하고 그것이 회문 일 경우 인쇄하십시오.

둘째, 공백을주의하십시오. 각 word의 끝에 개행 문자가 있습니다.

공백으로 인해 문장을 식별하지 않으므로 목록에서 모든 항목을 제거하려고 시도합니다. 당신이 반복하는 동안!

이 솔루션은 두 번째에서 잘 실행 회문 많은 식별 :

for word in open('/usr/share/dict/words', 'r'): 
    word = word.strip() 
    if ispalindrome(word): 
     print word 

편집을 :

def ispalindrome(a): 
    return a[::-1].lower() == a.lower() 

words = (word.strip() for word in open('/usr/share/dict/words', 'r')) 
palindromes = (word for word in words if ispalindrome(word)) 
print '\n'.join(palindromes) 
+0

이상한 점은 비록 그가 회문이 아닌 경우 목록에서 항목을 제거하기 때문에 모든 항목을 하나씩 제거해야한다는 것입니다. –

+0

@ 팀 : 아하 ... 예. 네가 옳아. 이렇게하면 목록에서 * 모든 것을 제거하려고 시도하지만 iterating이 반복됩니다. 추잡한! – Johnsyweb

2
:

아마도 더 '파이썬'generator 표현을 사용하는 것입니다

모든 단어를 반환하지는 않습니다. 그것은 반을 반환합니다. 이것은 반복하면서 목록을 수정하고 있기 때문에 실수입니다. 더 간단하고 효과적인 솔루션은 목록 이해력을 사용하는 것입니다. 당신은 모든 일을 할 석버 년대를 수정할 수 있습니다 : 당신은이를 분리 할 수 ​​있습니다

[word for word in (word.strip() for word in wl.readlines()) if ispalindrome(word)] 

:

stripped = (word.strip() for word in wl.readlines()) 
wordlist = [word for word in stripped if ispalindrome(word)] 
3

다른 사람이 이미 더 나은 솔루션을 지적했다.코드를 실행 한 후 목록이 비어 있지 않은 이유를 보여 드리려고합니다. ispalindrome() 함수는 다른 답변에서 언급 한 "개행 문제"로 인해 True을 반환하지 않으므로 코드는 모든 단일 항목에 wordlist.remove(x)을 호출합니다. 그렇다면 목록이 왜 비어 있지 않은지?

목록을 반복하면서 수정할 수 있기 때문에. 다음 고려 :

>>> l = [1,2,3,4,5,6] 
>>> for i in l: 
...  l.remove(i) 
... 
>>> l 
[2, 4, 6] 

당신이 1을 제거

은, 요소의 나머지 부분은 위쪽으로 한 단계 이동, 이제 l[0]2입니다. 반복 카운터가 진행되었지만 다음 반복에서 l[1]을보고 따라서 3 등을 제거합니다.

그래서 코드는 항목의 절반을 제거합니다. 도덕 : 목록을 반복하는 동안 목록을 수정하지 마십시오 (정확히 무엇을하고 있는지 알지 못하는 한 :)).