2016-06-17 9 views
3

Ich versuche, eine Liste zu durchlaufen, aber gleichzeitig Bezug auf die Elemente vor, so dass ich vergleichen kann.Python-Referenz vorhergehende Elemente in der Liste loop

Dies ist mein Code:

list1=[(1,'a','hii'),(2,'a','byee'),(3,'a','yoo'),(4,'b','laa'),(5,'a','mehh')] 

ich durch meine list1 Tupeln Schleife wollen, so dass, wenn der zweite Wert in dem Tupel ist der gleiche Wert wie der zweite Wert in dem Tupel vor (beide = = 'a'), dann concat den dritten Gegenstand im Tupel.

Ausgang Ich möchte:

list2=[('a','hii,byee,yoo'),('b','laa'),('a','mehh')] 

Was ich habe versucht,:

for item in list1: 
    for item2 in list2: 
      if item[0]==(item2[0]-1) and item[1]==item2[1]: 
        print item[2]+','+item2[2] 
      elif item[0] != item2[0]-1: 
        continue 
      elif item[0]==(item2[0]-1) and item[1] != item2[1]: 
        print item[2] 

falschen Ausgang

hii,byee 
byee,yoo 
yoo 
laa 

Von den ersten 2 Ausgaben scheint es so, als ob die Schleife nur den vorhergehenden Wert, aber nicht etwa 2 oder mehr vorhergehenden Wert betrachtet. Daher hat es nur 2 Wörter zusammengefügt und nicht 3, die es haben sollte. Die Ausgabe endet auch mit Wiederholungen.

Wie kann ich das umgehen?

+0

Do willst du nur benachbarte Tupel zusammenführen? Das heißt, die ersten drei werden alle zusammengeführt, aber die letzte, mit "mehh", geht nicht mit den Listen von vorne zusammen. – Blckknght

+0

Es muss benachbart sein und der zweite Wert des Tupels muss gleich sein (beide == 'a' oder ein anderer Wert) und das erste Element des Tupels muss um eins größer sein als das vorherige. So könnte es sein sei zuerst 3 oder zuerst 'n', wenn es die Anforderungen erfüllt. Außerdem ist meine Liste bereits nach dem ersten Wert des Tupels sortiert. – jxn

Antwort

4

Ich machte diese Weise schwieriger als es

def combine(inval): 
    outval = [inval[0]] 
    for item in inval[1:]: 
     if item[0] == outval[-1][0] + 1 and item[1] == outval[-1][1]: 
      outval[-1] = (item[0], item[1], ",".join([outval[-1][2], item[2]])) 
      continue 
     outval.append(item) 
    return [(item[1], item[2]) for item in outval] 

Und um es zu testen ...

list1 = [(1,'a','hii'),(2,'a','byee'),(3,'a','yoo'),(4,'b','laa'),(5,'a','mehh')] 
list2 = [(1,'a','hii'),(3,'a','byee'),(4,'a','yoo'),(5,'b','laa'),(6,'a','mehh')] 
list3 = [(1,'a','hoo'),(3,'a','byee'),(5,'a','yoo'),(6,'a','laa'),(7,'a','mehh'),(9, 'b', 'nope')] 

for l in (list1, list2, list3): 
    print "IN:", l 
    print "OUT:", combine(l) 
    print 

OUTPUT

IN: [(1, 'a', 'hii'), (2, 'a', 'byee'), (3, 'a', 'yoo'), (4, 'b', 'laa'), (5, 'a', 'mehh')] 
OUT: [('a', 'hii,byee,yoo'), ('b', 'laa'), ('a', 'mehh')] 

IN: [(1, 'a', 'hii'), (3, 'a', 'byee'), (4, 'a', 'yoo'), (5, 'b', 'laa'), (6, 'a', 'mehh')] 
OUT: [('a', 'hii'), ('a', 'byee,yoo'), ('b', 'laa'), ('a', 'mehh')] 

IN: [(1, 'a', 'hoo'), (3, 'a', 'byee'), (5, 'a', 'yoo'), (6, 'a', 'laa'), (7, 'a', 'mehh'), (9, 'b', 'nope')] 
OUT: [('a', 'hoo'), ('a', 'byee'), ('a', 'yoo,laa,mehh'), ('b', 'nope')] 

Diese kümmert sich um beide bürge sein musste laufende Nummern im 0.-Index sowie gleiche Werte im 1.-Index.

+0

Ich habe zuvor keine Anforderung bezüglich des sequentiellen Index-0-Elements bemerkt. Das wird das ein bisschen ändern. – sberry

+0

Siehe EDIT mit einer viel einfacheren, funktionierenden Lösung. – sberry

2

Edit: Ich habe den Algorithmus entsprechend den Anforderungen aktualisiert. Sie können alle Tupel mit demselben Schlüssel gruppieren, indem Sie group (values, sort = True) aufrufen oder nur benachbarte Tupel mit demselben Schlüssel gruppieren, indem Sie group (values) aufrufen. Dieser Algorithmus sammelt auch alle Elemente nach dem Schlüssel für das letzte Tupel, anstatt nur das dritte Element zu greifen.

GroupBy macht das ziemlich gut. Sie können die Werte nach dem zweiten Element im Tupel gruppieren. Dann für jede Gruppe, die alle die dritten Elemente in der Gruppe greifen und kommen sie in einen String:

import itertools 

def keySelector(tup): 
    return tup[1] 

def group(values, sort=False): 
    """ 
    Group tuples by their second element and return a list of 
    tuples (a, b) where a is the second element and b is the 
    aggregated string containing all of the remaining contents 
    of the tuple. 

    If sort=True, sort the tuples before grouping. This will 
    group all tuples with the same key. Otherwise, only adjacent 
    tuples wth the same key will be grouped. 
    """ 

    if sort: 
     values.sort(key=keySelector) 

    grouped = itertools.groupby(values, key=keySelector) 

    result = [] 
    for k, group in grouped: 

     # For each element in the group, grab the remaining contents of the tuple 
     allContents = [] 
     for tup in group: 
      # Convert tuple to list, grab everything after the second item 
      contents = list(tup)[2:] 
      allContents.extend(contents) 

     # Concatenate everything into one string 
     aggregatedString = ','.join(allContents) 

     # Add to results 
     result.append((k, aggregatedString)) 

    return result 

vals = [(1,'a','hii','abc','def'), 
     (2,'a','byee'), 
     (3,'a','yoo'), 
     (4,'b','laa'), 
     (5,'a','mehh','ghi','jkl')] 

print(group(vals, sort=True)) 

Ausgang:

[('a', 'hii,abc,def,byee,yoo,mehh,ghi,jkl'), ('b', 'laa')] 

Verkürzte Version mit Listenkomprehensionen:

def getGroupContents(tuples): 
    return ','.join(item for tup in tuples for item in list(tup)[2:]) 

def group(values, sort=False): 
    if sort: 
     values.sort(key=keySelector) 

    grouped = itertools.groupby(values, key=keySelector) 
    return [(k, getGroupContents(tuples)) for k, tuples in grouped] 
+0

Sie können 'keySelector' durch [' itemgetter (1) '] (https://docs.python.org/2/library/operator.html#operator.itemgetter) ersetzen. –

+0

Wie kann es nach dem zweiten Element gruppieren, aber nicht das letzte aufnehmen? (5, 'a', 'mehh') '? – jxn

+0

Wie kann ich die anderen Elemente im Tupel behalten? wie wenn mein Tupel hätte (5, 'a', 'mehh', 'xyz', 'abc') und ich möchte alles in der Ausgabe haben? – jxn

Verwandte Themen