Объединение элементов кортежа в списке в 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.