Résultats de la concaténation de deux fonctions de portée

la fonction range permet-elle la concaténation ? Comme je veux faire un range(30) & concaténer avec range(2000, 5002). Donc ma gamme concaténée sera 0, 1, 2, ... 29, 2000, 2001, ... 5001

ce Code ne fonctionne pas sur mon dernier python (version: 3.3.0)

range(30) + range(2000, 5002)
40
demandé sur Lev Levitsky 2012-12-31 13:34:12

7 réponses

Vous pouvez utiliser itertools.chain pour ceci:

from itertools import chain
concatenated = chain(range(30), range(2000, 5002))
for i in concatenated:
     ...

cela fonctionne pour les itérables arbitraires. Noter qu'il y a une différence dans le comportement de range() entre Python 2 et 3 que vous devriez connaître: en Python 2 range renvoie une liste, et en Python3 un itérateur, ce qui est efficace en mémoire, mais pas toujours souhaitable.

Listes peuvent être concaténées avec +, les itérateurs ne peuvent pas.

43
répondu Lev Levitsky 2012-12-31 09:48:56

peut être fait en utilisant liste-de la compréhension.

>>> [i for j in (range(10), range(15, 20)) for i in j]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 17, 18, 19]

Fonctionne pour votre demande, mais c'est une longue réponse, donc je ne vais pas le poster ici.

remarque: peut être fait dans un générateur pour des performances accrues:

for x in (i for j in (range(30), range(2000, 5002)) for i in j):
    # code

ou même dans une variable de générateur.

gen = (i for j in (range(30), range(2000, 5002)) for i in j)
for x in gen:
    # code
29
répondu Inbar Rose 2012-12-31 09:59:06

j'aime les solutions les plus simples qui sont possibles (y compris l'efficacité). Il n'est pas toujours clair si la solution est telle. De toute façon, le range() en Python 3 est un générateur. Vous pouvez l'enrouler à n'importe quelle construction qui fait itération. list() est capable de construire une valeur de liste à partir de n'importe quelle valeur itérable. + l'opérateur pour les listes fait la concaténation. J'utilise des valeurs plus petites dans l'exemple:

>>> list(range(5))
[0, 1, 2, 3, 4]
>>> list(range(10, 20))
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> list(range(5)) + list(range(10,20))
[0, 1, 2, 3, 4, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

c'est Ce que range(5) + range(10, 20) exactement fait en python 2.5 -- parce que range() retourné une liste.

en Python 3, Il n'est utile que si vous voulez vraiment construire la liste. Sinon, je recommande l' Lev Lev Levitsky's solution avec itertools.de la chaîne. La documentation montre également la mise en œuvre très simple:

def chain(*iterables):
    # chain('ABC', 'DEF') --> A B C D E F
    for it in iterables:
        for element in it:
            yield element

la solution par Inbar Rose est fine et fonctionnellement équivalent. Quoi qu'il en soit, Mon +1 va à Lev Lev Levitsky et à son argument sur l'utilisation des bibliothèques standard. À partir de le Zen de Python...

face à l'ambiguïté, refusez la tentation de deviner.

#!python3
import timeit
number = 10000

t = timeit.timeit('''\
for i in itertools.chain(range(30), range(2000, 5002)):
    pass
''',
'import itertools', number=number)
print('itertools:', t/number * 1000000, 'microsec/one execution')

t = timeit.timeit('''\
for x in (i for j in (range(30), range(2000, 5002)) for i in j):
    pass
''', number=number)
print('generator expression:', t/number * 1000000, 'microsec/one execution')

À mon avis, le itertools.chain est plus lisible. Mais ce qui est vraiment important...

itertools: 264.4522138986938 microsec/one execution
generator expression: 785.3081048010291 microsec/one execution

... il est environ 3 fois plus vite.

23
répondu pepr 2017-05-23 12:26:10

range() en Python 2.x renvoie une liste:

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

xrange() en Python 2.x renvoie un itérateur:

>>> xrange(10)
xrange(10)

et en Python 3 range() renvoie un itérateur:

>>> r = range(10)
>>> iterator = r.__iter__()
>>> iterator.__next__()
0
>>> iterator.__next__()
1
>>> iterator.__next__()
2

il est donc clair que vous ne pouvez pas concaténer d'autres itérateurs en utilisant chain() comme d'autres gars l'ont signalé.

4
répondu Andreas Jung 2017-02-23 04:59:28

Avec l'aide de l'étendre méthode, on peut concaténer deux listes.

>>> a = list(range(1,10))
>>> a.extend(range(100,105))
>>> a  
[1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 101, 102, 103, 104]
4
répondu Sivachandran 2017-03-24 18:52:03

j'en suis venu à cette question parce que j'essayais de concaténer un nombre inconnu de plages, qui pourraient se chevaucher, et je ne voulais pas de valeurs répétées dans l'itérateur final. Ma solution était d'utiliser set et union opérateur like:

range1 = range(1,4)
range2 = range(2,6)
concatenated = set.union(set(range1), set(range2)
for i in concatenated:
    print(i)
1
répondu raphael 2016-10-28 21:58:18

je sais que c'est un peu vieux thread, mais pour moi, les œuvres suivantes.

>>> for i in range(30) + range(2000, 5002):
...    print i

Donc

>>> for i in range(30) , range(2000, 5002):
...  print i

bien sûr, la sortie d'impression est différente dans le 2e à partir de la 1ère.

Edit: j'ai manqué le formulaire de commentaire de suivi de L'OP déclarant python 3. C'est dans mon environnement python 2.

0
répondu R J 2018-03-30 00:47:02