2016-04-18 28 views
-2

Ich habe eine Liste von Zahlen, zum Beispiel:Erstellen Sie eine Liste von Tupeln mit benachbarten Zahlen?

a = [1, 2, 3, 6, 9, 10] 

ich eine Funktion func schreiben möchten, die Liste und erzeugt Tupeln benachbarter Zahlen nimmt, so zum Beispiel die Liste wäre das Ergebnis

sein
func(a) == [(1,2,3), (6,), (9,10)] 

Was wäre ein effizienter Weg, dies zu tun?

+5

Sie bitten uns, eine Funktion für Sie zu schreiben? Teilen Sie, was Sie gemacht haben – Leva7

+0

und was ist das Problem? Gehe einfach durch die Liste und überprüfe, ob die 'Zahl - vorhergehende> 1 'in diesem Fall eine neue Liste von Zahlen startet und sie zum Ergebnis-Array hinzufügt – JohnnyAW

+0

@ Leva7 soweit alles was ich weiß ist, dass ich die Unterschiede zwischen den Listen brauche Elemente, dh '[ts für s, t in zip (a, a [1:])]' aber dann hinterlässt das nur eine Folge von 1s und eine andere Zahl, die die Sprünge repräsentiert – jk1093

Antwort

2

Hier ist ein individueller Generator:

def yield_adjacent(lst): 
    it = iter(lst) 
    sub = [next(it)] 
    while True: 
     try: 
      n = next(it) 
     except StopIteration: 
      yield tuple(sub) 
      raise 
     if n - sub[-1] == 1: 
      sub.append(n) 
     else: 
      yield tuple(sub) 
      sub = [n] 

Demo:

>>> a = [1, 2, 3, 6, 9, 10] 
>>> list(yield_adjacent(a)) 
[(1, 2, 3), (6,), (9, 10)] 
>>> a = [] 
>>> list(yield_adjacent(a)) 
[] 
>>> a = [1, 3] 
>>> list(yield_adjacent(a)) 
[(1,), (3,)] 
>>> a = [1, 3, 4, 9] 
>>> list(yield_adjacent(a)) 
[(1,), (3, 4), (9,)] 

edit: for Schleife Version:

def yield_adjacent(lst): 
    it = iter(lst) 
    sub = [next(it)] 
    for n in it: 
     if n - sub[-1] == 1: 
      sub.append(n) 
     else: 
      yield tuple(sub) 
      sub = [n] 
    yield tuple(sub) 
+1

Es ist eine wundervolle Antwort. Es ist eine Variante der äquivalenten Implementierung von "itertools.groupby", wie in den Dokumenten angegeben. –

+0

Es wäre klarer mit einer For-Schleife anstelle einer While-Schleife, meiner Meinung nach – wim

+0

@wim so? – timgeb

0

Wenn Sie nach einem netten "funktionalen" Weg suchen, würde ich groupby in iwertools verwenden, wir müssen nur eine Funktion entwickeln, die einen Wert hat, wenn Elemente sequentiell sind und ein anderer, wenn sie nicht sind. Wir können nicht Zustand in der Funktion, die in groupby übergeben wird, so dass wir einen Verschluss verwenden:

from itertools import groupby 

def group_sequential(els): 
    # enumerate els to get index along with value 
    return [y for (x,y) in groupby(enumerate(els), lambda (idx,_): els[idx]-els[idx-1] if idx != 0 else 1)) 

bearbeiten: fixed Fehler in vorherigen Code.

+0

Neben dem 'groupbuy' offensichtlichen Tippfehler, ist das wirklich gültige python3-Syntax? :) –

+0

Ja, sollte es sein, ich habe keinen Python-Interpreter auf dieser Box, aber es sollte in der Nähe sein. Ich bin nicht so vertraut mit 3, aber es sollte Wert python 2 sein. –

+0

die Syntax für Lambdas in Python3 ist anders als in 2, also bin ich mir ziemlich sicher, es ist der Lambda, der einen Syntaxfehler wirft – jk1093

0

Hier ist eine Funktion, die funktionieren soll:

def consec(l): 
    chunks = [i for i in range(1, len(l)) if l[i]-1 != l[i-1]]+[len(l)] 
    i = 0 
    for c in chunks: 
     yield(tuple(l[i:c])) 
     i = c 
Verwandte Themen