molostoff
molostoff

Reputation: 61

How to convert python tuple into a two dimentional table?

a flat (one dimension) tuple on input:

data = ('a','b','c'.....'z');

output: table (two dimensions) that has n (say 9) columns

table = ?what code here?

so

print table
 ( ('a','b','c'...), ('k','l','m','n'...), ....)

which is the shortest way to do so?

Upvotes: 2

Views: 5126

Answers (5)

larsks
larsks

Reputation: 312868

Here's the short version if you find the rest of this too wordy:

n = 9
table = zip(*[iter(data)]*n)

Let's say you start with a list:

>>> data = range(1,101)
>>> data
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
99, 100]

Create an iterator for your list:

>>> data_iter = iter(data)

Now use the zip function to split up the list. Pay attention, this is the fun part!

>>> table = zip(*[data_iter]*9)
>>> pprint.pprint(table)
[(1, 2, 3, 4, 5, 6, 7, 8, 9),
 (10, 11, 12, 13, 14, 15, 16, 17, 18),
 (19, 20, 21, 22, 23, 24, 25, 26, 27),
 (28, 29, 30, 31, 32, 33, 34, 35, 36),
 (37, 38, 39, 40, 41, 42, 43, 44, 45),
 (46, 47, 48, 49, 50, 51, 52, 53, 54),
 (55, 56, 57, 58, 59, 60, 61, 62, 63),
 (64, 65, 66, 67, 68, 69, 70, 71, 72),
 (73, 74, 75, 76, 77, 78, 79, 80, 81),
 (82, 83, 84, 85, 86, 87, 88, 89, 90),
 (91, 92, 93, 94, 95, 96, 97, 98, 99)]

The expression `[data_iter]*9' results in the following list:

[ data_iter, data_iter, data_iter, data_iter, data_iter, 
data_iter, data_iter, data_iter, data_iter ]

The expresion *[data_iter]*9 turns this into nine arguments to the zip function. This zip function builds a list of tuples:

Return a list of tuples, where each tuple contains the i-th element from each of the argument sequences. The returned list is truncated in length to the length of the shortest argument sequence.

Because we're using an iterator, every time zip function looks for a new value it gets the next value in the sequence. Contrast this with the behavior if we had simply used a list the same way:

>>> table = zip(*[data]*9)
>>> pprint.pprint(table)
[(1, 1, 1, 1, 1, 1, 1, 1, 1),
 (2, 2, 2, 2, 2, 2, 2, 2, 2),
 (3, 3, 3, 3, 3, 3, 3, 3, 3),
 ...
 (99, 99, 99, 99, 99, 99, 99, 99, 99),
 (100, 100, 100, 100, 100, 100, 100, 100, 100)]

UPDATE: My colleague points out that if you have NumPy available, you can do this:

>>> data = numpy.array(range(1,101))
>>> data.reshape([10,10])
array([[  1,   2,   3,   4,   5,   6,   7,   8,   9,  10],
   [ 11,  12,  13,  14,  15,  16,  17,  18,  19,  20],
   [ 21,  22,  23,  24,  25,  26,  27,  28,  29,  30],
   [ 31,  32,  33,  34,  35,  36,  37,  38,  39,  40],
   [ 41,  42,  43,  44,  45,  46,  47,  48,  49,  50],
   [ 51,  52,  53,  54,  55,  56,  57,  58,  59,  60],
   [ 61,  62,  63,  64,  65,  66,  67,  68,  69,  70],
   [ 71,  72,  73,  74,  75,  76,  77,  78,  79,  80],
   [ 81,  82,  83,  84,  85,  86,  87,  88,  89,  90],
   [ 91,  92,  93,  94,  95,  96,  97,  98,  99, 100]])

Upvotes: 8

richardw
richardw

Reputation: 768

Daenth,

The zip method described by larsks (above) is described in the itertools module documentation - search for "grouper" among the recipes:

Upvotes: 0

gsbabil
gsbabil

Reputation: 7703

>>> n = 3
>>> data = ('a', 'b', 'c', 'd', 'e', 'f',
...        'g', 'h', 'i', 'j', 'k', 'l',
...        'm', 'n')

>>> table = []    

>>> for i in xrange( 0, divmod( len(data), n)[0] + 1):
...     table.append( data[i*n:i*n+n] )

>>> print tuple( table )
(('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i'), ('j', 'k', 'l'), ('m', 'n'))

Upvotes: 0

How about this:

table = tuple(data[n:n+9] for n in xrange(0,len(data),9))

Returns a tuple made from stepping through data 9 items at a time. If you want to change the number of columns, just change both nines in the generator

Upvotes: 2

Daenyth
Daenyth

Reputation: 37471

I'm surprised this isn't in itertools, but it doesn't seem to be. Here's my approach:

def segment_list(lst, step):
    """
    Segment lst into a list of step-length lists
    """
    segments = []
    while True:
        if len(lst) <= step:
            output.append(lst)
            break
        output.append(lst[0:step])
        lst = lst[step+1:]
    return segments

Upvotes: 0

Related Questions