Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python reference preceding items in list loop

Tags:

python

loops

list

I am trying to loop through a list but at the same time make reference to the items before so i can compare.

This is my code:

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

I want to loop through my list1 tuples such that if the second value in the tuple is the same value as the second value in the tuple before (both =='a'), then concat the third item in the tuple.

output i want:

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

What i have tried:

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]

wrong output

hii,byee
byee,yoo
yoo
laa

From the first 2 output, it seems like the loop only looks at the preceding value but not at say 2 or more value preceding. Hence it only joined 2 words together and not 3 which it should have. The output also ends up having repeats.

How do i get around this?

like image 527
jxn Avatar asked Jun 11 '26 11:06

jxn


2 Answers

I was making this WAY harder than it needed to be

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]

And to test it...

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

This takes care of both guaranteeing sequential numbers at the 0th-index as well as equal values at the 1st-index.

like image 97
sberry Avatar answered Jun 13 '26 02:06

sberry


Edit: I've updated the algorithm according to the requirements. You can group all tuples with the same key by calling group(values, sort=True) or only group adjacent tuples with the same key by calling group(values). This algorithm also gathers all elements after the key for the final tuple instead of only grabbing the third element.

GroupBy does this pretty well. You can group the values by the second element in the tuple. Then for each group, grab all of the third elements in the group and join them into one 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))

Output:

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

Shortened version with list comprehensions:

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]
like image 40
tmajest Avatar answered Jun 13 '26 02:06

tmajest



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!