2017-01-26 1 views
2

Ich habe eine Liste sagen l = [1,5,8,-3,6,8,-3,2,-4,6,8]. Ich versuche, es in Unterlisten von positiven ganzen Zahlen zu teilen, d. H. Die obige Liste würde mir [[1,5,8],[6,8],[2],[6,8]] geben. Ich habe folgendes versucht:Python: Split-Liste basierend auf negativen ganzen Zahlen

l = [1,5,8,-3,6,8,-3,2,-4,6,8] 
index = 0 
def sublist(somelist): 
    a = [] 
    for i in somelist: 
     if i > 0: 
      a.append(i) 
     else: 
      global index 
      index += somelist.index(i) 
      break 
    return a 

print sublist(l) 

Damit kann ich die erste Teilliste erhalten ([1,5,8]) und die Indexnummer der ersten negativen ganzen Zahl an 3. Jetzt, wenn ich meine Funktion wieder laufen lasse und l[index+1:] übergebe, kann ich die nächste Unterliste nicht bekommen und nehme an, dass index aktualisiert wird, um 6 zu zeigen. Jedoch kann ich nicht, für das Leben von mir nicht herausfinden, wie man die Funktion in einer Schleife oder welche Bedingung zu verwenden, damit ich meine Funktion weiter laufen lassen und l[index+1:] geben kann, wobei index die aktualisierte, zuletzt angetroffene Position eines Negativs ist ganze Zahl. Jede Hilfe wird sehr geschätzt werden

Antwort

4

Sie müssen hier zwei Ebenen der Liste verfolgen - die große Liste, die die Unterlisten enthält, und die Unterlisten selbst. Starten Sie eine große Liste, starten Sie eine Unterliste und fügen Sie sie der aktuellen Unterliste hinzu, während i nicht negativ ist (was positive Zahlen und 0 enthält). Wenn i negativ ist, hängen Sie die aktuelle Unterliste an die große Liste an und starten Sie eine neue Unterliste. Beachten Sie auch, dass Sie Fälle behandeln sollten, in denen das erste Element negativ oder das letzte Element nicht negativ ist.

l = [1,5,8,-3,6,8,-3,2,-4,6,8] 

def sublist(somelist): 
    result = [] 
    a = [] 
    for i in somelist: 
     if i > 0: 
      a.append(i) 
     else: 
      if a: # make sure a has something in it 
       result.append(a) 
      a = [] 
    if a: # if a is still accumulating elements 
     result.append(a) 
    return result 

Das Ergebnis:

>>> sublist(l) 
[[1, 5, 8], [6, 8], [2], [6, 8]] 
+0

Im nicht sicher, ob ich voll und ganz die zweiten verstehen 'wenn ein:' Aussage – letsc

+0

@letsc - Seit sublist 'a' nur' result' angehängt wird, wenn Sie eine negative Zahl auftreten, Weglassen, dass die zweiten 'wenn ein: 'würde bedeuten, dass positive Zahlen am Ende der Eingabeliste zu 'a' addiert werden, aber 'a' niemals zu 'result' addiert wird. – TigerhawkT3

+0

Oooh !! Fantastisch. Danke vielmals! Ich akzeptiere diese Antwort, da sie als 1. geschrieben wurde und dem Code, den ich bereits habe, am nächsten kommt. Die anderen 2 Antworten funktionieren auch. – letsc

3

Seit somelist ändert sich nie, index rerunning immer Index der ersten Instanz eines Elements erhalten, nicht die, die Sie gerade erreicht. Ich schlage vor, enumerate zu betrachten, um den Index und das Element zu erhalten, während Sie loopen, also sind keine Anrufe zum Index notwendig.

Das heißt, könnten Sie die mitgelieferten Batterien verwenden diese als Einzeiler zu lösen, mit itertools.groupby:

from itertools import groupby 

def sublist(somelist): 
    return [list(g) for k, g in groupby(somelist, key=(0).__le__) if k] 

noch lohnt zu arbeiten durch den Code zu verstehen, aber die oben wird schnell sein würde und ziemlich einfach.

+0

würde ich a verwenden Lambda-Funktion, ich denke, das ist klarer – Copperfield

+0

@Copperfield: Natürlich ist 'Lambda x: x> = 0 'eine Option, aber ich vermeide' lambda's grundsätzlich (ich beschränke sie auf Fälle, wo es unmöglich ist, sie zu vermeiden also wenn ich einen benutze, weiß ich, dass es komplex ist), aber ich gebe zu, dass der direkte Zugriff auf die speziellen, reichen Vergleichsmethoden hässlich ist. Eine Alternative, die immer noch die höhere Geschwindigkeit von C-Level-Built-Ins ('Lambda's sind langsam) und benannte Funktionen mit voller Dokumentation wäre' key = functools.partial (operator.le, 0) ', obwohl dies beinhaltet zusätzliche Importe. – ShadowRanger

0

Nur zum Spaß können Sie re auch für einen einzigen Liner verwenden.

l = [1,5,8,-3,6,8,-3,2,-4,6,8] 
print map(lambda x: map(int,x.split(",")), re.findall(r"(?<=[,\[])\s*\d+(?:,\s*\d+)*(?=,\s*-\d+|\])", str(l))) 

Ausgang: [[1, 5, 8], [6, 8], [2], [6, 8]]

1

Dieser Code nutzt Konzepte unter dieser URL gefunden: Python list comprehension- "pop" result from original list?

ein interessantes Konzept hier, um Ihr Problem gefunden Auftragen, sind die folgenden einige Alternativen zu, was andere haben für diese Frage bisher gepostet. Beide verwenden List Comprehensions und werden kommentiert, um den Zweck der zweiten Option gegenüber der ersten zu erläutern. Haben Sie dieses Experiment für mich als Teil meiner Lernkurve, aber ich hoffe, es kann Ihnen und anderen in diesem Thread auch helfen:

Was ist nett an diesen ist, dass, wenn Ihre Eingabeliste sehr sehr groß ist, Sie nicht haben werden verdoppeln Sie Ihren Speicheraufwand, um die Aufgabe zu erledigen. Sie bauen eine auf, während Sie die andere verkleinern.

Dieser Code wurde auf Python 2.7 und Python 3 getestet.6:

o1 = [1,5,8,-3,6,9,-4,2,-5,6,7,-7, 999, -43, -1, 888]  
           # modified version of poster's list 
o1b = [1,5,8,-3,6,8,-3,2,-4,6,8] # poster's list 

o2 = [x for x in (o1.pop() for i in range(len(o1))) \ 
if (lambda x: True if x < 0 else o1.insert(0, x))(x)] 

o2b = [x for x in (o1b.pop() for i in range(len(o1b))) \ 
if (lambda x: True if x < 0 else o1b.insert(0, x))(x)] 

print(o1) 
print(o2) 
print("") 

print(o1b) 
print(o2b) 

Es erzeugt Ergebnismengen wie folgt (auf ipython Jupyter Notebooks):

[1, 5, 8, 6, 9, 2, 6, 7, 999, 888]
[ 1, 5, 8, 6, 8, 2, 6, 8]
[-4, -3, -3 ]

Hier ist eine andere Version, die auch List Comprehensions als Arbeitspferd verwendet, aber den Code in einer Weise funktionalisiert, die besser lesbar ist (I denke) und einfacher mit verschiedenen numerischen Listen zu testen. Einige werden wahrscheinlich den ursprünglichen Code bevorzugen, da es kürzer ist:

p1 = [1,5,8,-3,6,9,-4,2,-5,6,7,-7, 999, -43, -1, 888]  
           # modified version of poster's list 
p1b = [1,5,8,-3,6,8,-3,2,-4,6,8] # poster's list 

def lst_mut_byNeg_mod(x, pLst):  # list mutation by neg nums module 
    # this function only make sense in context of usage in 
    # split_pos_negs_in_list() 

    if x < 0: return True 
    else: 
     pLst.insert(0,x) 
     return False 

def split_pos_negs_in_list(pLst): 
    pLngth = len(pLst)    # reduces nesting of ((())) 
    return [x for x in (pLst.pop() for i in range(pLngth)) \ 
      if lst_mut_byNeg_mod(x, pLst)] 

p2 = split_pos_negs_in_list(p1) 
print(p1) 
print(p2) 
print("") 
p2b = split_pos_negs_in_list(p1b) 
print(p1b) 
print(p2b) 

Final Thoughts: angegebenen Link früher hatte eine Reihe von Ideen in dem Kommentar-Thread:

  • Es empfiehlt eine Google-Suche nach dem " Python bloom filter library "- das klingt vielversprechend aus der Sicht der Performance, aber ich habe noch nicht untersucht
  • Es gibt einen Beitrag zu diesem Thema mit 554 abgestimmt, und es hat mindestens 4 Kommentare erklären, was möglicherweise fehlerhaft ist damit. Beim Erkunden von Optionen kann es ratsam sein, den Kommentarpfad zu scannen und nicht nur zu überprüfen, was die meisten Stimmen erhält. Für solche Situationen werden viele Optionen vorgeschlagen.
Verwandte Themen