Объединение элементов кортежа в списке в python

У меня есть список кортежей, в котором есть строки Например:

[('this', 'is', 'a', 'foo', 'bar', 'sentences')
('is', 'a', 'foo', 'bar', 'sentences', 'and')
('a', 'foo', 'bar', 'sentences', 'and', 'i')
('foo', 'bar', 'sentences', 'and', 'i', 'want')
('bar', 'sentences', 'and', 'i', 'want', 'to')
('sentences', 'and', 'i', 'want', 'to', 'ngramize')
('and', 'i', 'want', 'to', 'ngramize', 'it')]

Теперь я хочу объединить каждую строку в кортеже, чтобы создать список разделенных пробелом строк. Я использовал следующий метод:

NewData=[]
for grams in sixgrams:
       NewData.append( (''.join([w+' ' for w in grams])).strip())

который работает отлично.

Однако список, который у меня есть, содержит более миллиона кортежей. Поэтому мой вопрос в том, что этот метод достаточно эффективен или есть лучший способ сделать это. Спасибо.

Ответы

Ответ 1

Для большого количества данных вы должны подумать, нужно ли хранить все это в списке. Если вы обрабатываете каждый из них за один раз, вы можете создать генератор, который даст каждую объединенную строку, но не будет держать их вокруг занимаемой памяти:

new_data = (' '.join(w) for w in sixgrams)

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

Ответ 2

Понимание списка создает временные строки. Просто используйте ' '.join вместо этого.

>>> words_list = [('this', 'is', 'a', 'foo', 'bar', 'sentences'),
...               ('is', 'a', 'foo', 'bar', 'sentences', 'and'),
...               ('a', 'foo', 'bar', 'sentences', 'and', 'i'),
...               ('foo', 'bar', 'sentences', 'and', 'i', 'want'),
...               ('bar', 'sentences', 'and', 'i', 'want', 'to'),
...               ('sentences', 'and', 'i', 'want', 'to', 'ngramize'),
...               ('and', 'i', 'want', 'to', 'ngramize', 'it')]
>>> new_list = []
>>> for words in words_list:
...     new_list.append(' '.join(words)) # <---------------
... 
>>> new_list
['this is a foo bar sentences', 
 'is a foo bar sentences and', 
 'a foo bar sentences and i', 
 'foo bar sentences and i want', 
 'bar sentences and i want to', 
 'sentences and i want to ngramize', 
 'and i want to ngramize it']

Выше цикла for может быть выражено следующим образом:

new_list = [' '.join(words) for words in words_list] 

Ответ 3

Вы можете сделать это эффективно, как это

joiner = " ".join
print map(joiner, sixgrams)

Мы все еще можем улучшить производительность, используя понимание списка, подобное этому

joiner = " ".join
print [joiner(words) for words in sixgrams]

Сравнение производительности показывает, что решение, описанное выше, доступно немного быстрее, чем другие два решения.

from timeit import timeit

joiner = " ".join

def mapSolution():
    return map(joiner, sixgrams)

def comprehensionSolution1():
    return ["".join(words) for words in sixgrams]

def comprehensionSolution2():
    return [joiner(words) for words in sixgrams]

print timeit("mapSolution()", "from __main__ import joiner, mapSolution, sixgrams")
print timeit("comprehensionSolution1()", "from __main__ import sixgrams, comprehensionSolution1, joiner")
print timeit("comprehensionSolution2()", "from __main__ import sixgrams, comprehensionSolution2, joiner")

Выход на моей машине

1.5691678524
1.66710209846
1.47555398941

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

Изменить: Хотя мы можем улучшить производительность, как это, самый pythonic путь - пойти с генераторами, как в lvc answer.