Domanda

Voglio un algoritmo per iterare su lista fette. dimensione fette sorge fuori della funzione e può variare.

Nella mia mente è qualcosa di simile:

for list_of_x_items in fatherList:
    foo(list_of_x_items)

C'è un modo per definire correttamente list_of_x_items o qualche altro modo di fare questo usando Python 2.5?


edit1: Chiarimento Entrambi i termini "partizionamento" e "finestra scorrevole" Sound applicabile al mio compito, ma non sono un esperto. Così vi spiegherò il problema un po 'più profondo e aggiungere alla domanda:

Il fatherList è un numpy.array multilivello sto ottenendo da un file. Funzione deve trovare medie di serie (utente fornisce la lunghezza della serie) per la media Sto usando la funzione mean(). Ora per l'espansione domanda:

EDIT2: Come modificare la funzione che avete fornito per memorizzare gli elementi in più e li usa quando il prossimo fatherList è alimentato alla funzione

?

per esempio se la lista è lunghezza 10 e la dimensione di un blocco è 3, quindi il 10 ° membro della lista viene memorizzato e aggiunta all'inizio della lista seguente.


Related:

È stato utile?

Soluzione

risposta all'ultima parte della domanda:

  

Aggiornamento domanda: Come modificare la   funzione che ci ha fornito per memorizzare   gli oggetti extra e li usa quando il   prossimo fatherList viene alimentato al   Funzione?

Se avete bisogno di memorizzare lo stato quindi è possibile utilizzare un oggetto per questo.

class Chunker(object):
    """Split `iterable` on evenly sized chunks.

    Leftovers are remembered and yielded at the next call.
    """
    def __init__(self, chunksize):
        assert chunksize > 0
        self.chunksize = chunksize        
        self.chunk = []

    def __call__(self, iterable):
        """Yield items from `iterable` `self.chunksize` at the time."""
        assert len(self.chunk) < self.chunksize
        for item in iterable:
            self.chunk.append(item)
            if len(self.chunk) == self.chunksize:
                # yield collected full chunk
                yield self.chunk
                self.chunk = [] 

Esempio:

chunker = Chunker(3)
for s in "abcd", "efgh":
    for chunk in chunker(s):
        print ''.join(chunk)

if chunker.chunk: # is there anything left?
    print ''.join(chunker.chunk)

Output:

abc
def
gh

Altri suggerimenti

Se si desidera dividere un elenco a fette è possibile utilizzare questo trucco:

list_of_slices = zip(*(iter(the_list),) * slice_size)

Ad esempio

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

Se il numero di elementi non è divisibile per la dimensione fetta e si desidera pad alla lista con Nessuno si può fare questo:

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

E 'un po' sporco trucco


OK, ti spiego come funziona. Sarà difficile da spiegare, ma farò del mio meglio.

Prima un po 'di storia:

In Python è possibile moltiplicare un elenco da un numero come questo:

[1, 2, 3] * 3 -> [1, 2, 3, 1, 2, 3, 1, 2, 3]
([1, 2, 3],) * 3 -> ([1, 2, 3], [1, 2, 3], [1, 2, 3])

E un oggetto iteratore può essere consumato una volta come questo :

>>> l=iter([1, 2, 3])
>>> l.next()
1
>>> l.next()
2
>>> l.next()
3

Il href="http://docs.python.org/library/functions.html#zip" zip funzione restituisce una lista di tuple, dove la i-esima tupla contiene l'elemento i-esimo da ciascuna delle sequenze argomenti o iterabili. Ad esempio:

zip([1, 2, 3], [20, 30, 40]) -> [(1, 20), (2, 30), (3, 40)]
zip(*[(1, 20), (2, 30), (3, 40)]) -> [[1, 2, 3], [20, 30, 40]]

Il * di fronte a zip utilizzata per decomprimere argomenti. Potete trovare maggiori dettagli href="http://docs.python.org/tutorial/controlflow.html#unpacking-argument-lists" qui . Quindi

zip(*[(1, 20), (2, 30), (3, 40)])

è in realtà equivalente a

zip((1, 20), (2, 30), (3, 40))

ma funziona con un numero variabile di argomenti

Ora torniamo al trucco:

list_of_slices = zip(*(iter(the_list),) * slice_size)

iter(the_list) -> convertire l'elenco in un iteratore

(iter(the_list),) * N -> genererà un riferimento N per la_lista iteratore

.

zip(*(iter(the_list),) * N) -> alimenteranno quelli elenco di iteratori in zip. Che a sua volta li gruppo volontà in N dimensioni tuple. Ma dal momento che tutti gli elementi N sono infatti riferimenti allo stesso iteratore iter(the_list) il risultato sarà ripetuta per le chiamate next() sull'iteratore originale

Mi auguro che lo spiega. Vi consiglio di andare con una più facile da capire soluzione. Ero tentato solo per citare questo trucco perché mi piace.

Se si vuole essere in grado di consumare qualsiasi iterabile è possibile utilizzare queste funzioni:

from itertools import chain, islice

def ichunked(seq, chunksize):
    """Yields items from an iterator in iterable chunks."""
    it = iter(seq)
    while True:
        yield chain([it.next()], islice(it, chunksize-1))

def chunked(seq, chunksize):
    """Yields items from an iterator in list chunks."""
    for chunk in ichunked(seq, chunksize):
        yield list(chunk)

Vuoi dire qualcosa come:

def callonslices(size, fatherList, foo):
  for i in xrange(0, len(fatherList), size):
    foo(fatherList[i:i+size])

Se questo è più o meno la funzionalità che si desidera si potrebbe, se lo desideri, vestire in su un po 'in un generatore:

def sliceup(size, fatherList):
  for i in xrange(0, len(fatherList), size):
    yield fatherList[i:i+size]

e poi:

def callonslices(size, fatherList, foo):
  for sli in sliceup(size, fatherList):
    foo(sli)

Usa un generatore:

big_list = [1,2,3,4,5,6,7,8,9]
slice_length = 3
def sliceIterator(lst, sliceLen):
    for i in range(len(lst) - sliceLen + 1):
        yield lst[i:i + sliceLen]

for slice in sliceIterator(big_list, slice_length):
    foo(slice)

sliceIterator implementa una "finestra scorrevole" di larghezza sliceLen sul lst squence, cioè produce sovrapposizione fette: [1,2,3], [2,3,4], [3,4,5], .. . Non sono sicuro se questa è l'intenzione del PO, però.

Non sono sicuro, ma sembra che si vuole fare quello che viene chiamato una media mobile. NumPy offre caratteristiche (la funzione convolve).

>>> x = numpy.array(range(20))
>>> x
    array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19])    
>>> n = 2 # moving average window
>>> numpy.convolve(numpy.ones(n)/n, x)[n-1:-n+1]
array([  0.5,   1.5,   2.5,   3.5,   4.5,   5.5,   6.5,   7.5,   8.5,
         9.5,  10.5,  11.5,  12.5,  13.5,  14.5,  15.5,  16.5,  17.5,  18.5])

La cosa bella è che ospita diversi schemi di ponderazione bene (basta cambiare numpy.ones(n) / n a qualcos'altro).

È possibile qui trovare un materiale completo: http://www.scipy.org/Cookbook/SignalSmooth

La tua domanda potrebbe usare un po 'più in dettaglio, ma come su:

def iterate_over_slices(the_list, slice_size):
    for start in range(0, len(the_list)-slice_size):
        slice = the_list[start:start+slice_size]
        foo(slice)

Per un quasi-one liner (dopo l'importazione itertools) in vena di risposta di Nadia si tratta di non-Chunk size divisibili senza imbottitura:

>>> import itertools as itt
>>> chunksize = 5
>>> myseq = range(18)
>>> cnt = itt.count()
>>> print [ tuple(grp) for k,grp in itt.groupby(myseq, key=lambda x: cnt.next()//chunksize%2)]
[(0, 1, 2, 3, 4), (5, 6, 7, 8, 9), (10, 11, 12, 13, 14), (15, 16, 17)]

Se si vuole, si può sbarazzarsi del requisito itertools.count() utilizzando enumerate(), con un piuttosto brutta:

[ [e[1] for e in grp] for k,grp in itt.groupby(enumerate(myseq), key=lambda x: x[0]//chunksize%2) ]

(In questo esempio il enumerate() sarebbe superflua, ma non tutte le sequenze sono gamme pulito come questo, ovviamente)

Nulla vicino così pulito come alcune altre risposte, ma utile in un pizzico, soprattutto se già l'importazione itertools.

Ampliando la risposta di @Ants Aasma: In Python 3.7 la gestione dell'eccezione StopIteration cambiato (secondo PEP-479 ) . Una versione compatibile potrebbe essere:

from itertools import chain, islice

def ichunked(seq, chunksize):
    it = iter(seq)
    while True:
        try:
            yield chain([next(it)], islice(it, chunksize - 1))
        except StopIteration:
            return
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top