J'ai une liste de tuples contenant des chaînes Par exemple:
[('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')]
Maintenant, je souhaite concaténer chaque chaîne dans un tuple pour créer une liste de chaînes séparées par des espaces. J'ai utilisé la méthode suivante:
NewData=[]
for grams in sixgrams:
NewData.append( (''.join([w+' ' for w in grams])).strip())
qui fonctionne parfaitement bien.
Cependant, la liste que j'ai contient plus d'un million de tuples. Ma question est donc de savoir si cette méthode est suffisamment efficace ou existe-t-il une meilleure façon de le faire. Merci.
Pour beaucoup de données, vous devez vous demander si vous besoin pour tout garder dans une liste. Si vous traitez chacun à la fois, vous pouvez créer un générateur qui produira chaque chaîne jointe, mais ne les gardera pas tout autour de la mémoire:
new_data = (' '.join(w) for w in sixgrams)
si vous pouvez également obtenir les tuples d'origine à partir d'un générateur, vous pouvez également éviter d'avoir la liste sixgrams
en mémoire.
La compréhension de la liste crée des chaînes temporaires. Utilisez simplement ' '.join
au lieu.
>>> 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']
Au-dessus de for
, la boucle peut être exprimée comme la compréhension de la liste suivante:
new_list = [' '.join(words) for words in words_list]
Vous pouvez le faire efficacement comme ceci
joiner = " ".join
print map(joiner, sixgrams)
Nous pouvons encore améliorer les performances en utilisant la compréhension de liste comme celle-ci
joiner = " ".join
print [joiner(words) for words in sixgrams]
La comparaison des performances montre que la solution de compréhension de liste ci-dessus est légèrement plus rapide que les deux autres solutions.
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")
Sortie sur ma machine
1.5691678524
1.66710209846
1.47555398941
Le gain de performances est très probablement dû au fait que nous n'avons pas à créer la fonction de jointure à partir de la chaîne vide à chaque fois.
Edit: Bien que nous puissions améliorer les performances comme ceci, la façon la plus Pythonique est d'utiliser des générateurs comme dans réponse de lvc .