2010-02-11 23 views
3

En utilisant Python, j'essaye de convertir une phrase de mots en une liste plate de toutes les lettres distinctes dans cette phrase.Comment passer d'une liste de mots à une liste de lettres distinctes en Python

Voici mon code actuel:

words = 'She sells seashells by the seashore' 

ltr = [] 

# Convert the string that is "words" to a list of its component words 
word_list = [x.strip().lower() for x in words.split(' ')] 

# Now convert the list of component words to a distinct list of 
# all letters encountered. 
for word in word_list: 
    for c in word: 
     if c not in ltr: 
      ltr.append(c) 

print ltr 

Ce code renvoie ['s', 'h', 'e', 'l', 'a', 'b', 'y', 't', 'o', 'r'], ce qui est correct, mais est-il un moyen plus Pythonic à cette réponse, probablement à l'aide de la liste compréhensions/set?

Lorsque j'essaie de combiner l'imbrication et le filtrage de la liste, j'obtiens des listes de listes au lieu d'une liste à plat.

L'ordre des lettres distinctes dans la liste finale (ltr) n'est pas important; Ce qui est crucial, c'est qu'ils soient uniques.

+1

+1 pour une question bien formulée et y compris votre tentative (quel spectacle de bienvenue!) – bernie

+0

Notez que 'defaults str.split' pour le fractionnement sur les espaces, donc' .split (» ') 'est généralement orthographié' .split() '. –

Répondre

13

Sets offrent une solution simple et efficace.

words = 'She sells seashells by the seashore' 

unique_letters = set(words.lower()) 
unique_letters.discard(' ') # If there was a space, remove it. 
+0

c'est le gagnant :) – SilentGhost

+0

à peu près la même chose que ephemient, mais votre réponse si formaté plus agréable. – tgray

+1

Très bien!5chars – danben

3
set([letter.lower() for letter in words if letter != ' ']) 

Modifier: Je viens d'essayer et trouvé cela aussi travailler (peut-être c'est ce que SilentGhost faisait référence à):

set(letter.lower() for letter in words if letter != ' ') 

Et si vous avez besoin d'avoir une liste plutôt qu'une ensemble, vous pouvez

list(set(letter.lower() for letter in words if letter != ' ')) 
+1

vous ne répertoriez pas la compréhension – SilentGhost

+0

@Art Metzer: Notez que le fractionnement n'est pas vraiment nécessaire, car une chaîne est un type itérable. C'est probablement pourquoi vous obteniez des listes de listes quand vous ne les vouliez pas. – danben

+0

@SilentGhost: Je ne comprends pas votre commentaire, pouvez-vous clarifier? – danben

3

Faire ltr un ensemble et changer votre corps en boucle un peu:

ltr = set() 

for word in word_list: 
    for c in word: 
     ltr.add(c) 

ou en utilisant une compréhension de la liste:

ltr = set([c for word in word_list for c in word]) 
0
set(l for w in word_list for l in w) 
+0

Cela comprendra des espaces. – danben

+0

@danben: Vous * avez * remarqué que 'word_list' est déjà divisé par des espaces, n'est-ce pas? –

+0

Ah, désolé - j'ai mal lu comme pour w dans les mots ... ' – danben

2
 
>>> set('She sells seashells by the seashore'.replace(' ', '').lower()) 
set(['a', 'b', 'e', 'h', 'l', 'o', 's', 'r', 't', 'y']) 
>>> set(c.lower() for c in 'She sells seashells by the seashore' if not c.isspace()) 
set(['a', 'b', 'e', 'h', 'l', 'o', 's', 'r', 't', 'y']) 
>>> from itertools import chain 
>>> set(chain(*'She sells seashells by the seashore'.lower().split())) 
set(['a', 'b', 'e', 'h', 'l', 'o', 's', 'r', 't', 'y']) 
2

voici quelques timings faits avec Py3K:

>>> import timeit 
>>> def t():     # mine (see history) 
    a = {i.lower() for i in words} 
    a.discard(' ') 
    return a 

>>> timeit.timeit(t) 
7.993071812372081 
>>> def b():     # danben 
    return set(letter.lower() for letter in words if letter != ' ') 

>>> timeit.timeit(b) 
9.982847967921138 
>>> def c():     # ephemient in comment 
    return {i.lower() for i in words if i != ' '} 

>>> timeit.timeit(c) 
8.241267610375516 
>>> def d():     #Mike Graham 
    a = set(words.lower()) 
    a.discard(' ') 
    return a 

>>> timeit.timeit(d) 
2.7693045186082372 
+0

' {i.lower() pour i dans les mots si i! = ''} 'Fonctionne aussi. – ephemient

+0

@ ephemient: ça marche, mais c'est un peu plus lent. et btw, 'set (i.lower pour i dans les mots si i! = '')' version est 20% plus lent dans py3k – SilentGhost

0
words = 'She sells seashells by the seashore' 

ltr = list(set(list(words.lower()))) 
ltr.remove(' ') 
print ltr 
+0

oh, mon chéri, oh mon dieu, oh mon dieu ... voici la lecture utile: http://docs.python.org/reference/ datamodel.html # the-standard-type-hierarchy – SilentGhost