web-dev-qa-db-fra.com

Concaténer les éléments d'un Tuple dans une liste dans python

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.

19
alphacentauri

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.

22
lvc

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] 
7
falsetru

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 .

6
thefourtheye