2015-12-18 13 views
6

eine EingangslisteGruppenelemente einer Liste mit einer Schrittgröße python?

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

und Gruppengröße grp und Schritt Schritt

grp = 3; step = 2 

Gegeben Ich mag eine Liste zurückkehren würde. Beachten Sie die Wiederholung am Ende

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

oder wenn

grp= 4; step = 2 

sollte die Ausgabe

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

Dies ist der Code, den ich mit ihm kam sein nicht die zyklische Sache. Aber würde gerne wissen, ob es eine kleinere oder eine einfachere Lösung

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

Für mich die beiden Beispiele Konflikt. Bitte zeigen Sie eine für Schritt = 1. Oder sollte das Beispiel 1 sein? – Pynchia

+0

@Pynchia die beiden Beispiele nicht in Konflikt stehen. Beide haben "step = 2", also sollte die erste Zahl in der zweiten Zeile "3" sein. – SirParselot

+3

Warum für GRP 4 Schritt 2 wickeln wir zurück zu 1 statt zu 10? – wim

Antwort

3

ist Sie Vorteil der Stufenfunktion in xrange oder Bereich je nachdem, welche Version von Python Sie verwenden nehmen. Dann wickeln wieder um nur durch die Länge der Liste mod wie so

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

Danke Aber ich habe auch eine Follow-up-Frage. Ich mache das tatsächlich für Strings und die Ausgabe, die ich bekomme, ist in der Form ['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'] Weißt du, wie ich die 'und die [] und Kommas entfernen konnte ?? –

+0

@ArsenalFanatic zu mir, das aussieht, als ob es eine Liste von Listen ist, die Sie loswerden können die "[]" durch Drucken sie anstatt die Liste selbst zu drucken. – 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 

Beispiel Ausgang:

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

eine Deque Verwendung:

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) 

output:

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

Sie können ebenfalls in das Islice Objekt ergeben und entscheiden, was Sie mit ihm tun mögen außen:

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

Ausgang:

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 

Oder nur mit 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 ... Ich arbeitete für etwas wie Ihre Antwort, aber Sie überholten mich ... fantastisch ... :) –

+2

Die Deque-Idee ist schön. – wim

+1

@PadraicCunningham ... Mind Sharing einige Ressourcen über die Arbeit mit Itertools und Sammlungen Modul..wie ich Ihre Antworten gefolgt bin und ich sehe, dass Sie eine Menge ihrer Methoden verwenden ... Danke ..:) –

0

Hier ist noch eine andere Lösung, die Indizes beim Scannen nicht verwendet. Stattdessen werden die gefundenen Elemente gespeichert und mit den folgenden Elementen verkettet.

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) 

produziert

[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

Das Paket iteration_utilities hat eine Funktion für diese Art von Fensterextraktion Schiebe 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 

Angewandt auf Ihre Beispiele:

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

Das Paket enthält auch eine Komfort-Klasse 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 

Beachten Sie, dass diese Operationen Generator-basiert sind, so dass die Auswertung verschoben wird, bis Sie über sie (zum Beispiel durch eine list Schaffung) iterieren.


Bitte beachte, dass ich den Autor iteration_utilities bin. Es gibt mehrere andere Pakete auch ähnliche Funktionen bereitstellt, das heißt more-itertools und toolz

0

Ab Version 2.5, more_itertools.windowed unterstützt eine step Stichwort.

> pip install more_itertools 

Anwendung:

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

funktioniert der Trick in einer Zeile

+0

Das ist ziemlich cool – pylang

+0

Es sollte jedoch angemerkt werden, dass 'l + l' _ach jeder Iteration_ unglaublich effizient ist! – MSeifert

+0

l2 = l + l; [l2 [x: x + grp] für x, _ in Liste (enumerate (l)) [:: step]] löst das Problem – louis35

Verwandte Themen