2010-02-11 5 views
3

Используя Python, я пытаюсь преобразовать предложение слов в плоский список всех различных букв в этом предложении.Как перейти из списка слов в список различных букв в Python

Вот мой текущий код:

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 

Этот код возвращает ['s', 'h', 'e', 'l', 'a', 'b', 'y', 't', 'o', 'r'], который является правильным, но есть более Pythonic способ этот ответ, вероятно, с помощью списковых/set?

Когда я пытаюсь объединить вложение и фильтрацию списка, я получаю списки списков вместо плоского списка.

Порядок отдельных букв в конечном списке (ltr) не имеет значения; важно то, что они уникальны.

+1

+1 за хорошо сформулированный вопрос и в том числе вашу попытку (то, что долгожданное зрелище!) – bernie

+0

Обратите внимание, что 'str.split' по умолчанию к расщеплению на пробелы, поэтому' .split (» ') 'обычно пишется' .split() '. –

ответ

13

Наборы обеспечивают простое и эффективное решение.

words = 'She sells seashells by the seashore' 

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

это победитель :) – SilentGhost

+0

в значительной степени то же, что и ephemient, но ваш ответ, если отформатировать лучше. – tgray

+1

Очень приятно!5chars – danben

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

Edit: Я просто попробовал и нашел, что это будет работать (возможно, это то, что SilentGhost имел в виду):

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

И если вам нужно иметь список, а не набор, вы можете

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

Вы не указали это понимание – SilentGhost

+0

@Art Metzer: Обратите внимание, что разделение на самом деле не требуется, поскольку строка является итерируемым типом. Вероятно, поэтому вы получали списки списков, когда вы их не хотели. – danben

+0

@SilentGhost: Я не понимаю ваш комментарий, вы можете уточнить? – danben

3

Сделать ltr набор и изменить ваше тело цикла немного:

ltr = set() 

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

Или, используя список понимание:

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

Это будет пространство. – danben

+0

@danben: Вы * заметили, что 'word_list' уже разделен пробелами, не так ли? –

+0

Ах, извините - я неправильно читал как 'для w в словах ...' – 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

вот некоторые тайминги, сделанные с 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() для i в словах, если i! = ''}' Работает тоже. – ephemient

+0

@ephemient: он работает, но он немного медленнее. и btw, 'set (i.lower для i в словах, если i! = '')' версия на 20% медленнее в py3k – SilentGhost

0
words = 'She sells seashells by the seashore' 

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

о, дорогая, о, дорогая, о, дорогая ... вот полезная информация: http://docs.python.org/reference/ datamodel.html # заместитель стандартного типа иерархии – SilentGhost