2013-04-30 2 views
3

Предположим, у вас есть список таких каксписок Python кортежей, нужно распаковать и очистить

x = [('Edgar',), ('Robert',)]

Что бы наиболее эффективным способом, чтобы добраться до всего строк 'Edgar' и 'Robert'?

Не хотите, чтобы x [0] [0], например.

+1

Самый эффективный способ будет зависеть от того, что вы планируете с ними делать потом. Например, нет смысла создавать новый список, если вы собираетесь перебирать этот список позже. Если это так, более эффективно просто сделать что-то вроде: 'for (i,) в x: do_something_with (i)'. – Aya

+0

Мне нужно отправить эту строку в другую функцию. –

ответ

6

простого решение, и самый быстрый в большинстве случаев.

[item[0] for item in x] 
#or 
[item for (item,) in x] 

В качестве альтернативы, если вам нужен функциональный интерфейс для доступа индекса (но немного медленнее):

from operator import itemgetter 

zero_index = itemgetter(0) 

print map(zero_index, x) 

Наконец, если последовательность слишком мал, чтобы поместиться в памяти, вы можете сделать это итеративно. Это намного медленнее в коллекциях, но использует память только одного элемента.

from itertools import chain 

x = [('Edgar',), ('Robert',)] 

# list is to materialize the entire sequence. 
# Normally you would use this in a for loop with no `list()` call. 
print list(chain.from_iterable(x)) 

Но если все, что вы собираетесь сделать, это перебирать в любом случае, вы можете просто использовать кортеж распаковку:

for (item,) in x: 
    myfunc(item) 
+0

Спасибо, очень признателен от коллеги философии младшего ребенка. –

+0

Почему вы говорите, что версия 'itemgetter' быстрее? – gatto

+0

Потому что я сумасшедший. Я думаю, что это было быстрее, но просто тестировалось на CPython 2.7, и это не так. Изменение ответа. –

1
>>> from operator import itemgetter 
>>> y = map(itemgetter(0), x) 
>>> y 
['Edgar', 'Robert'] 
>>> y[0] 
'Edgar' 
>>> y[1] 
'Robert' 
3

Это довольно просто с list comprehension:

x = [('Edgar',), ('Robert',)] 
y = [s for t in x for s in t] 

Это делает то же самое, как list(itertools.chain.from_iterable(x)) и эквивалентно в поведении на следующий код:

y = [] 
for t in x: 
    for s in t: 
     y.append(s) 
2

Мне нужно отправить эту строку в другую функцию.

Если ваше намерение просто вызвать функцию для каждой строки в списке, то нет никакой необходимости создавать новый список, просто ...

def my_function(s): 
    # do the thing with 's' 

x = [('Edgar',), ('Robert',)] 

for (item,) in x: 
    my_function(item) 

... или если вы «вновь готовы пожертвовать читаемость для исполнения, я подозреваю, что это самый быстрый, чтобы сделать ...

def my_function(t): 
    s = t[0]   
    # do the thing with 's' 
    return None 

x = [('Edgar',), ('Robert',)] 
filter(my_function, x)  

Оба map() и filter() будет делать итерации в C, а не Python байткод, но map() необходимо будет создать список значений той же длины входного списка, тогда как filter() будет строить только пустой список, если my_function() возвращает значение «falsish».

2

Вот один из способов:

>>> [name for name, in x] 
['Edgar', 'Robert'] 

Обратите внимание на расположение запятой, который распаковывает кортеж.