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?
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]])
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
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
>>> 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'))
Daenth,
The zip method described by larsks (above) is described in the itertools module documentation - search for "grouper" among the recipes:
- http://docs.python.org/library/itertools.html#recipes
精彩评论