2015-12-18 17 views
6

Dato una lista di ingressoRaggruppa elementi di un elenco con un python a gradini?

l = [1 2 3 4 5 6 7 8 9 10] 

e dimensione grp gruppo e passo passo

grp = 3; step = 2 

desidero restituire un elenco. Si noti la ripetizione alla fine

1 2 3 
3 4 5 
5 6 7 
7 8 9 
9 10 1 

o se

grp= 4; step = 2 

l'uscita dovrebbe essere

1 2 3 4 
3 4 5 6 
5 6 7 8 
7 8 9 10 

Questo è il codice mi è venuta con esso non fare la cosa ciclica. Ma vorrei sapere se v'è un minore o una soluzione più semplice

def grouplist(l,grp,step): 
    oplist = list() 
    for x in range(0,len(l)): 
     if (x+grp<len(l)): 
     oplist.append(str(l[x:x+grp])) 
    return oplist 
+0

Per me il conflitto due esempi. Si prega di mostrarne uno per passo = 1. O è quello che dovrebbe essere l'esempio 1? – Pynchia

+0

@Pynchia i due esempi non sono in conflitto. Entrambi hanno 'step = 2' quindi il primo numero sulla seconda riga dovrebbe essere' 3' quale è. – SirParselot

+3

Perché per grp 4 step 2 ci si riprende da 1 invece che da 10? – wim

risposta

3

È possibile sfruttare la funzione di passo nella xrange o intervallo a seconda di quale versione di Python che si sta utilizzando. Poi per avvolgere di nuovo intorno solo mod dalla lunghezza della lista in questo modo

import sys 

def grouplist(l,grp,step): 
    newlist=[] 
    d = len(l) 
    for i in xrange(0,len(l),step): 
     for j in xrange(grp): 
      newlist.append(l[(i+j)%d]) 
      sys.stdout.write(str(l[(i+j)%d]) + ' ') 
     print 

l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
print grouplist(l,3,2) 
1 2 3 
3 4 5 
5 6 7 
7 8 9 
9 10 1 
[1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 1] 

print grouplist(l,4,2) 
1 2 3 4 
3 4 5 6 
5 6 7 8 
7 8 9 10 
9 10 1 2 
[1, 2, 3, 4, 3, 4, 5, 6, 5, 6, 7, 8, 7, 8, 9, 10, 9, 10, 1, 2] 
+0

Grazie, ma ho anche una domanda di follow-up. Effettivamente lo faccio per le stringhe e l'output che ottengo è nel formato ['0_1_125.jpg', '0_1_126.jpg', '0_1_127.jpg'] ['0_1_126.jpg', '0_1_127.jpg', '0_1_128.jpg'] ['0_1_127.jpg', '0_1_128.jpg', '0_1_129.jpg'] Sai come potrei rimuovere il 'e il [] e le virgole ?? –

+0

@ArsenalFanatic per me che sembra un elenco di liste da cui puoi sbarazzarti di ''[]' stampandole invece di stampare la lista stessa. – SirParselot

2
def grouplist(L, grp, step): 
    starts = range(0, len(L), step) 
    stops = [x + grp for x in starts] 
    groups = [(L*2)[start:stop] for start, stop in zip(starts, stops)] 
    return groups 

def tabulate(groups): 
    print '\n'.join(' '.join(map(str, row)) for row in groups) 
    print 

uscita Esempio:

>>> tabulate(grouplist(range(1,11), 3, 2)) 
1 2 3 
3 4 5 
5 6 7 
7 8 9 
9 10 1 

>>> tabulate(grouplist(range(1,11), 4, 2)) 
1 2 3 4 
3 4 5 6 
5 6 7 8 
7 8 9 10 
9 10 1 2 
2

utilizzando una deque:

from itertools import islice 
from collections import deque 



def grps(l, gps, stp): 
    d = deque(l) 
    for i in range(0, len(l), stp): 
     yield list(islice(d, gps)) 
     d.rotate(-stp) 

uscita:

In [7]: l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

In [8]: list(grps(l, 3, 2)) 
Out[8]: [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10, 1]] 

In [9]: list(grps(l, 4, 2)) 
Out[9]: [[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8], [7, 8, 9, 10], [9, 10, 1, 2]] 

Puoi anche partecipare cedere l'oggetto iSlice e decidere cosa si vuole fare con esso al di fuori:

def grps(l, gps, stp): 
    d = deque(l) 
    for i in range(0, len(l), stp): 
     yield islice(d, gps) 
     d.rotate(-stp) 

uscita:

In [11]:  for gp in grps(l, 3,2): 
    ....:    print(" ".join(map(str,gp))) 
    ....:  
1 2 3 
3 4 5 
5 6 7 
7 8 9 
9 10 1 

O solo con modulo:

def grps(l, gps, stp): 
    ln = len(l) 
    for i in range(0, len(l), stp): 
     yield (l[j % ln] for j in range(i, i + gps)) 


for gp in grps(l, 4, 2): 
    print(" ".join(map(str, gp))) 
+2

@Padraic ... Stavo lavorando per qualcosa come la tua risposta, ma tu mi hai superato ... fantastico ... :) –

+2

L'idea di deque è carina. – wim

+1

@PadraicCunningham ... Mind Sharing alcune risorse su come lavorare con itertools e modulo di raccolta..come ho seguito le tue risposte e vedo che stai usando molti dei loro metodi ... grazie ..:) –

0

Ecco un'altra soluzione, che non utilizza gli indici della lista durante la scansione. Invece salva gli elementi incontrati da ripetere e li concatena con gli elementi che seguono.

def grplst(l, grp, stp): 
    ret = [] 
    saved = [] 
    curstp = 0 
    dx = grp - stp 
    for el in l: 
     curstp += 1 
     if curstp <= stp: 
      ret.append(el) 
     else: 
      saved.append(el) 
      if curstp >= grp: 
       yield ret+saved 
       ret = saved 
       saved = [] 
       curstp = dx 
    yield ret+l[:dx] 


l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

for g in grplst(l, 3, 2): 
    print(g) 

for g in grplst(l, 4, 2): 
    print(g) 

produce

[1, 2, 3] 
[3, 4, 5] 
[5, 6, 7] 
[7, 8, 9] 
[9, 10, 1] 

[1, 2, 3, 4] 
[3, 4, 5, 6] 
[5, 6, 7, 8] 
[7, 8, 9, 10] 
[9, 10, 1, 2] 
1

Il pacchetto iteration_utilities ha una funzione per questo tipo di scorrimento estrazione finestra successive:

from iteration_utilities import successive 
from itertools import chain, islice, starmap 

def wrapped_and_grouped_with_step(seq, groupsize, step, formatting=False): 
    padded = chain(seq, seq[:step-1]) 
    grouped = successive(padded, groupsize) 
    stepped = islice(grouped, None, None, step) 
    if formatting: 
     inner_formatted = starmap(('{} '*groupsize).strip().format, stepped) 
     outer_formatted = '\n'.join(inner_formatted) 
     return outer_formatted 
    else: 
     return stepped 

Applicando questa ai esempi:

>>> list(wrapped_and_grouped_with_step(l, 3, 2)) 
[(1, 2, 3), (3, 4, 5), (5, 6, 7), (7, 8, 9), (9, 10, 1)] 

>>> list(wrapped_and_grouped_with_step(l, 4, 2)) 
[(1, 2, 3, 4), (3, 4, 5, 6), (5, 6, 7, 8), (7, 8, 9, 10)] 

>>> print(wrapped_and_grouped_with_step(l, 3, 2, formatting=True)) 
1 2 3 
3 4 5 
5 6 7 
7 8 9 
9 10 1 

>>> print(wrapped_and_grouped_with_step(l, 4, 2, formatting=True)) 
1 2 3 4 
3 4 5 6 
5 6 7 8 
7 8 9 10 
012.

Il pacchetto include anche una classe di convenienza ManyIterables:

>>> from iteration_utilities import ManyIterables 
>>> step, groupsize = 2, 4 
>>> print(ManyIterables(l, l[:step-1]) 
...  .chain() 
...  .successive(groupsize) 
...  [::step] 
...  .starmap(('{} '*groupsize).strip().format) 
...  .as_string('\n')) 
1 2 3 4 
3 4 5 6 
5 6 7 8 
7 8 9 10 

Si noti che queste operazioni sono generatore-basa quindi la valutazione è rinviata al di eseguire iterazioni su di esso (ad esempio con la creazione di un list).


nota che io sono l'autore di iteration_utilities. Ci sono diversi altri pacchetti che offrono anche funzioni simili, vale a dire more-itertools e toolz

0

A partire dalla versione 2.5, supporta more_itertools.windowed una parola chiave step.

> pip install more_itertools 

Applicazione:

import itertools as it 

import more_itertools as mit 

def grouplist(l, grp, step): 
    """Yield a finite number of windows.""" 
    iterable = it.cycle(l) 
    cycled_windows = mit.windowed(iterable, grp, step=step) 
    last_idx = grp - 1 
    for i, window in enumerate(cycled_windows): 
     yield window 
     if last_idx >= len(l) - 1: 
      break 
     last_idx += (i * step) 


list(grouplist(l, 3, 2)) 
# Out: [(1, 2, 3), (3, 4, 5), (5, 6, 7), (7, 8, 9), (9, 10, 1)] 

list(grouplist(l, 4, 2)) 
# Out: [(1, 2, 3, 4), (3, 4, 5, 6), (5, 6, 7, 8), (7, 8, 9, 10)] 

list(mit.flatten(grouplist(l, 3, 2))))     # optional 
# Out: [1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 1] 
2
[(l+l)[x:x+grp] for x,_ in list(enumerate(l))[::step]] 

fa il trucco in una linea

+0

Questo è piuttosto bello – pylang

+0

Tuttavia si dovrebbe notare che fare 'l + l' _each iteration_ è incredibilmente inefficiente! – MSeifert

+0

l2 = l + l; [l2 [x: x + grp] per x, _ nella lista (enumerate (l)) [:: step]] risolve il problema – louis35

Problemi correlati