Traverse a list of tuples containg a string and list in python

364 Views Asked by At

I have a list of tuples which contains a string and another list. It is as follows:

board = [('10S', []), ('3H', []), ('6C', ['KS', '9C']), ('6H', []), ('7D', []), ('9S', ['AS', 'KS'])]

I want to traverse such that comparison is done as follows:

10S 3H
3H 6C
6C KS
6C 9C
6C 6H
6H 7D  

and so on...

That is the get_mapping() written below will call the values for prev2 and prev1.

I have implemented the following code:

for val in board:
    print "Val is: " + str(val)
    if cnt == 0:
        prev2 = val[0][0]
        prev1 = val[1][0]
        cnt += 1
        get_mapping(prev2,prev1,True)
    else:
        prev2 = prev1
        if len(val[1]) > 0:
            for v in val[1]:
                prev1 = v
                cnt += 1
                get_mapping(prev2,prev1,False)
        else:
            prev1 = val[0]
            cnt += 1
            get_mapping(prev2,prev1,True)    

I know the first condition is wrong. I am stuck a little as to how to traverse to get above comparison. Any help will be appreciated.

2

There are 2 best solutions below

2
On BEST ANSWER

You could write a generator yielding pairs:

from itertools import zip_longest

master_board_state = [('10S', []), ('3H', []), ('6C', ['KS', '9C']),
                      ('6H', []), ('7D', []), ('9S', ['AS', 'KS'])]

def pairs(state):
    for (key, lst), nxt in zip_longest(state, state[1:]):
        yield from ((key, x) for x in lst)
        if nxt is not None:
            yield key, nxt[0]

print('\n'.join(str(p) for p in pairs(master_board_state)))

Output:

('10S', '3H')
('3H', '6C')
('6C', 'KS')
('6C', '9C')
('6C', '6H')
('6H', '7D')
('7D', '9S')
('9S', 'AS')
('9S', 'KS')

In above zip_longest will yield items from state as pairs. Since first parameter is longer than second one on last iteration None is used as fillvalue. Then the loop will first yield from generator that returns (key, list item) tuples and finally yields current and next key.

Update For Python 2 minor modifications are required since it doesn't have yield from and zip_longest is known as izip_longest:

from itertools import izip_longest

master_board_state = [('10S', []), ('3H', []), ('6C', ['KS', '9C']),
                      ('6H', []), ('7D', []), ('9S', ['AS', 'KS'])]

def pairs(state):
    for (key, lst), nxt in izip_longest(state, state[1:]):
        for x in lst:
            yield key, x
        if nxt is not None:
            yield key, nxt[0]

print '\n'.join(str(p) for p in pairs(master_board_state))
2
On

So this is very specific kind of traversal, which can be done through a generator.

Update: initially tried with a complex generator expression but missed the tail so had to end up with a generator function similar to @niemmi but with a slightly different approach.

from itertools import tee

# from itertools recipes
def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

def pairs(d):
    for (a, x), (b, y) in pairwise(d):
        yield from ((a, n) for n in x)
        yield a, b
    yield from ((b, n) for n in y)

>>> list(pairs(board))
[('10S', '3H'),
 ('3H', '6C'),
 ('6C', 'KS'),
 ('6C', '9C'),
 ('6C', '6H'),
 ('6H', '7D'),
 ('7D', '9S'),
 ('9S', 'AS'),
 ('9S', 'KS')]