aaneenschakeling van twee bereikfunctiesresultaten

Hiermee kan de bereikfunctie aaneenschakeling mogelijk maken? Zoals ik wil een range(30)& AMP; Concatenate het met range(2000, 5002). Dus mijn aaneengeschakelde bereik is 0, 1, 2, ... 29, 2000, 2001, ... 5001

Code zoals dit werkt niet op mijn nieuwste Python (Ver: 3.3.0)

range(30) + range(2000, 5002)

Antwoord 1, Autoriteit 100%

U kunt itertools.chainHiervoor:

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

Het werkt voor arbitraire iterables. Merk op dat er een verschil is in gedrag van range()tussen Python 2 en 3 waarvan u moet weten: in Python 2 rangeretourneert een lijst, en in Python3 een iterator, die geheugen-efficiënt is, maar niet altijd wenselijk.

Lijsten kunnen worden samengevoegd met +, iterators niet.


Antwoord 2, Autoriteit 59%

Ik hou van de meest eenvoudige oplossingen die mogelijk zijn (inclusief efficiëntie). Het is niet altijd duidelijk of de oplossing zo is. Hoe dan ook, de range()in Python 3 is een generator. Je kunt het inpakken tot een construct die iteratie is. De list()is in staat om een ​​lijstwaarde te construeren van akelig. De +Operator voor lijsten doet aaneenschakeling. Ik gebruik kleinere waarden in het voorbeeld:

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

Dit is wat range(5) + range(10, 20)precies in Python 2.5 – omdat range()een lijst retourneert.

In Python 3 is het alleen handig als u de lijst echt wilt construeren. Anders adviseer ik de Levitsky’s oplossing met itertools.chain . De documentatie toont ook de zeer eenvoudige implementatie:

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

De oplossing door Inbar Rose is prima en functioneel equivalent. Hoe dan ook, mijn +1 gaat naar Levitsky en zijn argument over het gebruik van de standaardbibliotheken. Van de ZEN van Python

In het aangezicht van ambiguïteit, weigeren de verleiding om te raden.

#!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')

Naar mijn mening is de itertools.chainmeer leesbaar. Maar wat is echt belangrijk …

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

… het is ongeveer 3 keer sneller.


Antwoord 3, Autoriteit 45%

Kan worden gedaan met behulp van list-comprehension.

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

Werkt voor uw verzoek, maar het is een lang antwoord, dus ik zal het hier niet posten.

opmerking: kan worden omgezet in een generator voor betere prestaties:

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

of zelfs in een generatorvariabele.

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

Antwoord 4, autoriteit 37%

python >= 3,5

Je kunt iterable uitpakken gebruiken in lijsten (zie PEP 448: Aanvullende uitpak-generalisaties).

Als je een lijst nodig hebt,

[*range(2, 5), *range(3, 7)]
# [2, 3, 4, 3, 4, 5, 6]

Hiermee wordt de volgorde behouden en worden dubbele exemplaren niet verwijderd. Of misschien wil je een tupel,

(*range(2, 5), *range(3, 7))
# (2, 3, 4, 3, 4, 5, 6)

… of een set,

# note that this drops duplicates
{*range(2, 5), *range(3, 7)}
# {2, 3, 4, 5, 6}

Het is toevallig ook sneller dan het aanroepen van itertools.chain.

from itertools import chain
%timeit list(chain(range(10000), range(5000, 20000)))
%timeit [*range(10000), *range(5000, 20000)]
738 µs ± 10.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
665 µs ± 13.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Het voordeel van chainis echter dat je een willekeurige lijst met bereiken kunt doorgeven.

ranges = [range(2, 5), range(3, 7), ...]
flat = list(chain.from_iterable(ranges))

OTOH, generalisaties voor het uitpakken zijn niet “gegeneraliseerd” naar willekeurige reeksen, dus u zult de afzonderlijke reeksen nog steeds zelf moeten uitpakken.


Antwoord 5, autoriteit 11%

Met behulp van de extend-methode kunnen we twee lijsten samenvoegen.

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

Antwoord 6, autoriteit 5%

range()in Python 2.x geeft een lijst terug:

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

xrange()in Python 2.x retourneert een iterator:

>>> xrange(10)
xrange(10)

En in Python 3 retourneert range()ook een iterator:

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

Het is dus duidelijk dat je andere iterators niet kunt samenvoegen door chain()te gebruiken, zoals de andere man al zei.


Antwoord 7

Je kunt de lijstfunctie rond de bereikfunctie gebruiken om een ​​lijst te maken
LIKE DIT

list(range(3,7))+list(range(2,9))

Antwoord 8

Ik kwam tot deze vraag omdat ik probeerde een onbekend aantal bereiken samen te voegen, die elkaar zouden kunnen overlappen, en ik wilde geen herhaalde waarden in de uiteindelijke iterator. Mijn oplossing was om sette gebruiken en de unionoperator zoals:

range1 = range(1,4)
range2 = range(2,6)
concatenated = set.union(set(range1), set(range2)
for i in concatenated:
    print(i)

Other episodes