enumerate()-funktion vaativuus¶
Funktio enumerate() palauttaa iteraattorin, joka tuottaa (indeksi, alkio) -monikoita iteroituvasta.
Vaativuusanalyysi¶
| Tapaus | Aika | Tila | Huomiot |
|---|---|---|---|
| Iteraattorin luonti | O(1) | O(1) | Luo vain iteraattoriolion |
| Iteraattorin kuluttaminen | O(n) | O(1) | n = läpikäytyjen alkioiden määrä; tuottaa yhden kerrallaan |
| Oma aloitusarvo | O(n) | O(1) | start-parametri ei muuta vaativuutta |
Huomio: enumerate() palauttaa iteraattorin, joka tuottaa monikot laiskasti. Tilavaativuus on O(1), koska se ei säilytä kaikkia monikoita muistissa. Muuntaminen listaksi list(enumerate(x))-kutsulla vie O(n) tilaa.
Peruskäyttö¶
Yksinkertainen numerointi¶
# O(1) - creates iterator
items = ['a', 'b', 'c']
enumerated = enumerate(items) # Iterator
# O(n) - consumed when needed
for index, item in enumerated:
print(index, item)
# 0 a
# 1 b
# 2 c
# Convert to list - O(n) time and space
result = list(enumerate(items))
# [(0, 'a'), (1, 'b'), (2, 'c')]
Oma aloitusindeksi¶
# O(1) - creates iterator
items = ['a', 'b', 'c']
enumerated = enumerate(items, start=1)
# O(n) - consumed
result = list(enumerated)
# [(1, 'a'), (2, 'b'), (3, 'c')]
# Works with any start value
result = list(enumerate(items, start=10))
# [(10, 'a'), (11, 'b'), (12, 'c')]
Suorituskykymallit¶
Laiska evaluointi¶
# O(1) - creates iterator, doesn't process yet
big_list = range(10**9)
enumerated = enumerate(big_list)
# O(n) - only when you consume
for i, item in enumerate(big_list):
print(i, item)
if i >= 10:
break # O(10) - stops early
# vs list comprehension
result = [(i, x) for i, x in enumerate(range(10**9))] # O(10^9)!
Sisäkkäinen numerointi¶
# O(n*m*k) - enumerate nested structures
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# O(n*m) - enumerate rows and columns
for i, row in enumerate(matrix):
for j, item in enumerate(row):
print(f"[{i}][{j}] = {item}")
Yleisiä ratkaisumalleja¶
Iterointi indeksin kanssa¶
# ✅ O(n) - preferred way
items = ['a', 'b', 'c', 'd', 'e']
for index, item in enumerate(items):
print(index, item)
# ❌ O(n) but less Pythonic
for i in range(len(items)):
print(i, items[i])
# ❌ O(n) with unnecessary zip
for i, item in zip(range(len(items)), items):
print(i, item)
Suodatus indeksin avulla¶
# O(n) - enumerate and filter
items = ['a', 'b', 'c', 'd', 'e']
result = [item for i, item in enumerate(items) if i % 2 == 0]
# ['a', 'c', 'e']
# Get only indices
indices = [i for i, item in enumerate(items) if 'a' in item]
# [0]
Uuden rakenteen rakentaminen¶
# O(n) - enumerate to create dict
items = ['apple', 'banana', 'cherry']
item_dict = {i: item for i, item in enumerate(items)}
# {0: 'apple', 1: 'banana', 2: 'cherry'}
# With custom start
item_dict = {i: item for i, item in enumerate(items, start=1)}
# {1: 'apple', 2: 'banana', 3: 'cherry'}
Työskentely useiden iteroituvien kanssa¶
Rinnakkainen iterointi indeksin kanssa¶
# O(n) - enumerate with zip
names = ['Alice', 'Bob', 'Charlie']
ages = [30, 25, 35]
for i, (name, age) in enumerate(zip(names, ages)):
print(f"{i}: {name} is {age}")
# 0: Alice is 30
# 1: Bob is 25
# 2: Charlie is 35
Sisäkkäiset rakenteet¶
# O(n*m*k) - multiple levels of enumeration
data = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
for i, row in enumerate(data):
for j, item in enumerate(row):
print(f"[{i}][{j}] = {item}")
Edistyneet ratkaisumallit¶
enumerate oman indeksin kanssa¶
# O(n) - enumerate with offset
items = ['a', 'b', 'c', 'd', 'e']
for index, item in enumerate(items, start=100):
print(index, item)
# 100 a
# 101 b
# ... etc
Sijainnin etsiminen¶
# O(n) - find position of element
items = ['apple', 'banana', 'cherry', 'date']
target = 'cherry'
for index, item in enumerate(items):
if item == target:
position = index
break
# position = 2
# Alternative: use index() method
position = items.index(target) # O(n) - same complexity
Ehdollinen numerointi¶
# O(n) - enumerate with filter
items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Only enumerate even items
for index, item in enumerate(items):
if item % 2 == 0:
print(index, item)
# 1 2
# 3 4
# ... etc
Vertailu vaihtoehtoihin¶
enumerate vs range(len(...))¶
# ✅ enumerate - preferred, more Pythonic
items = ['a', 'b', 'c']
for i, item in enumerate(items):
print(i, item)
# ❌ range(len(...)) - less readable
for i in range(len(items)):
print(i, items[i])
# Both O(n), enumerate is clearer
enumerate vs zip ja range¶
# ✅ enumerate - simpler and faster
items = ['a', 'b', 'c']
for i, item in enumerate(items):
process(i, item)
# ❌ zip with range - unnecessary overhead
for i, item in zip(range(len(items)), items):
process(i, item)
# Both O(n), enumerate is more efficient
enumerate vs index()-metodi¶
# If finding position of one element
items = ['a', 'b', 'c', 'd', 'e']
target = 'c'
# O(n) - enumerate
for i, item in enumerate(items):
if item == target:
print(i)
break
# O(n) - index method
print(items.index(target))
# If finding multiple positions
# enumerate is more efficient - single pass
# If finding one - index() is clearer
Erikoistapaukset¶
Tyhjä iteroituva¶
# O(1) - creates empty iterator
result = list(enumerate([]))
# []
for i, item in enumerate([]):
print(i, item) # Never executes
Yksi alkio¶
# O(1) - creates iterator with one element
result = list(enumerate(['a']))
# [(0, 'a')]
Suuri aloitusarvo¶
# O(1) - start value doesn't affect complexity
result = list(enumerate([1, 2, 3], start=10**9))
# [(1000000000, 1), (1000000001, 2), (1000000002, 3)]
Generaattorit¶
# O(n) - enumerate can consume generators
def generator():
yield 1
yield 2
yield 3
for i, value in enumerate(generator()):
print(i, value)
# 0 1
# 1 2
# 2 3
Suorituskykyhuomioita¶
Muistitehokkuus¶
# ✅ Iterator - memory efficient
big_list = range(10**9)
for i, item in enumerate(big_list):
if i < 10:
print(item)
# Only iterates 10 items
# ❌ List creation - uses memory
indices_items = list(enumerate(range(10**9))) # Huge memory!
Nopeusvertailu¶
import timeit
items = list(range(1000))
# Time for enumerate
t1 = timeit.timeit(lambda: [x for i, x in enumerate(items)], number=10000)
# Time for range(len(...))
t2 = timeit.timeit(lambda: [items[i] for i in range(len(items))], number=10000)
# enumerate is generally faster due to optimizations
Parhaat käytännöt¶
✅ Tee näin:
- Käytä
enumerate()-funktiota, kun tarvitset sekä indeksin että alkion - Käytä
enumerate(iterable, start=1)-muotoa ykkösestä alkavaan indeksointiin - Käytä
enumerate()-funktiota yhdessäbreak-lauseen kanssa aikaiseen poistumiseen - Käytä
enumerate()-funktiota laiskaan evaluointiin suurilla aineistoilla
❌ Vältä:
range(len(...))-muodon käyttöä, kunenumerate()on selkeämpizip(range(len(...)), iterable)-muodon käyttöä - käytä sen sijaanenumerate()-funktiota- Unohtamasta, että
enumerate()palauttaa iteraattorin - Turhien välilistojen luomista
Liittyvät funktiot¶
- zip() - Yhdistää useita iteroituvia
- range() - Tuottaa lukujonoja
- iter() - Luo iteraattoreita
- next() - Hakee iteraattorin seuraavan alkion
Versiohuomiot¶
- Python 2.x:
enumerate()käytettävissä, toimii samaan tapaan - Python 3.x: Sama toiminta ja suorituskyky
- Python 3.8+: Optimoinnit voivat parantaa suorituskykyä, mutta O(n) on taattu