469,271 Members | 1,009 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,271 developers. It's quick & easy.

Printing n elements per line in a list

If have a list from 1 to 100, what's the easiest, most elegant way to
print them out, so that there are only n elements per line.

So if n=5, the printed list would look like:

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
etc.

My search through the previous posts yields methods to print all the
values of the list on a single line, but that's not what I want. I feel
like there is an easy, pretty way to do this. I think it's possible to
hack it up using while loops and some ugly slicing, but hopefully I'm
missing something

Aug 15 '06 #1
26 15931
"unexpected" <su***********@gmail.comwrites:
If have a list from 1 to 100, what's the easiest, most elegant way to
print them out, so that there are only n elements per line.

So if n=5, the printed list would look like:

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
etc.

My search through the previous posts yields methods to print all the
values of the list on a single line, but that's not what I want. I feel
like there is an easy, pretty way to do this. I think it's possible to
hack it up using while loops and some ugly slicing, but hopefully I'm
missing something
The most direct way would be something like (untested):

for i in xrange(0, 100, 5):
print ' '.join(str(j) for j in a[i:i+5])

where a is the array. If you prefer a "coordinate-free" style, you
could use something like:

for x,y in itertools.groupby(a, lambda n: n//5):
print ' '.join(str(k) for k in y)

I hope I got that right.
Aug 16 '06 #2
Paul Rubin <http://ph****@NOSPAM.invalidwrites:
for x,y in itertools.groupby(a, lambda n: n//5):
print ' '.join(str(k) for k in y)

I hope I got that right.
Of course I meant to say
for x,y in itertools.groupby(enumerate(a), lambda (n,x): n//5):
print ' '.join(str(k) for n,k in y)
This is still way ugly and I've never found a really good solution.
Aug 16 '06 #3
On 15 Aug 2006 16:51:29 -0700,
"unexpected" <su***********@gmail.comwrote:
If have a list from 1 to 100, what's the easiest, most elegant way to
print them out, so that there are only n elements per line.
So if n=5, the printed list would look like:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
etc.
My search through the previous posts yields methods to print all the
values of the list on a single line, but that's not what I want. I feel
like there is an easy, pretty way to do this. I think it's possible to
hack it up using while loops and some ugly slicing, but hopefully I'm
missing something
Perhaps not the prettiest, but I can't think of anything simpler to read
six months from now:

counter = 0
for an_element in the_list:
print an_element,
counter = counter + 1
if counter == n:
print
counter = 0

Regards,
Dan

--
Dan Sommers
<http://www.tombstonezero.net/dan/>
"I wish people would die in alphabetical order." -- My wife, the genealogist
Aug 16 '06 #4
unexpected wrote:
If have a list from 1 to 100, what's the easiest, most elegant way to
print them out, so that there are only n elements per line.

So if n=5, the printed list would look like:

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
etc.

My search through the previous posts yields methods to print all the
values of the list on a single line, but that's not what I want. I feel
like there is an easy, pretty way to do this. I think it's possible to
hack it up using while loops and some ugly slicing, but hopefully I'm
missing something
>From http://docs.python.org/lib/itertools-recipes.html there's the
grouper() function:

from itertools import izip, chain, repeat

def grouper(n, iterable, padvalue=None):
"""
Return n-tuples from iterable, padding with padvalue.
Example:
grouper(3, 'abcdefg', 'x') -->
('a','b','c'), ('d','e','f'), ('g','x','x')
"""
return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)

R = range(1, 101)

for N in grouper(5, R, ''):
print ' '.join(str(n) for n in N)

If your iterable is not a multiple of n (of course not the case for 100
and 5), and you don't want the extra spaces at the end of your last
line, you could join the lines with '\n' and stick a call to rstrip()
in there:

G = grouper(5, R, '')
print '\n'.join(' '.join(str(n) for n in N) for N in G).rstrip()

but then you're back to ugly. lol.

Peace,
~Simon

Aug 16 '06 #5

Dan Sommers wrote:
>
counter = 0
for an_element in the_list:
print an_element,
counter = counter + 1
if counter == n:
print
counter = 0
Yes, often simple old-fashioned ways are the best. A little verbose,
though. And I'd do some old-fashioned testing -- the above needs "if
counter: print" after the loop has finished, to get the final '\n' for
cases where there are not an even multiple of n elements.
>>def wrapn(alist, n):
.... ctr = 0
.... for item in alist:
.... print item,
.... ctr = (ctr + 1) % n
.... if not ctr:
.... print
.... if ctr:
.... print
....
>>for k in range(8):
.... print '--- %d ---' % k
.... wrapn(range(k), 3)
....
--- 0 ---
--- 1 ---
0
--- 2 ---
0 1
--- 3 ---
0 1 2
--- 4 ---
0 1 2
3
--- 5 ---
0 1 2
3 4
--- 6 ---
0 1 2
3 4 5
--- 7 ---
0 1 2
3 4 5
6
>>>
Cheers,
John

Aug 16 '06 #6
On Tue, 15 Aug 2006 16:51:29 -0700, unexpected wrote:
If have a list from 1 to 100, what's the easiest, most elegant way to
print them out, so that there are only n elements per line.

So if n=5, the printed list would look like:

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
etc.

My search through the previous posts yields methods to print all the
values of the list on a single line, but that's not what I want. I feel
like there is an easy, pretty way to do this. I think it's possible to
hack it up using while loops and some ugly slicing, but hopefully I'm
missing something
I don't see why you think that's an ugly hack.

def printitems(sequence, count=5):
"""Print count items of sequence per line."""
numrows = len(sequence)//count
if len(sequence)%count != 0: numrows += 1
for start in range(0, numrows):
items = sequence[start*count:(start+1)*count]
for item in items:
print item,
print

--
Steven D'Aprano

Aug 16 '06 #7

Steven D'Aprano wrote:
I think it's possible to
hack it up using while loops and some ugly slicing, but hopefully I'm
missing something

I don't see why you think that's an ugly hack.

def printitems(sequence, count=5):
"""Print count items of sequence per line."""
numrows = len(sequence)//count
if len(sequence)%count != 0: numrows += 1
for start in range(0, numrows):
items = sequence[start*count:(start+1)*count]
for item in items:
print item,
print
Ugliness is in the eye of the beholder.
It is more blessed to add than to multiply.
Gaze upon this alternative:

def printitems2(sequence, count=5):
"""Print count items of sequence per line."""
for pos in range(0, len(sequence), count):
for item in sequence[pos:pos+count]:
print item,
print

Cheers,
John

Aug 16 '06 #8
John Machin wrote:
Steven D'Aprano wrote:
I think it's possible to
hack it up using while loops and some ugly slicing, but hopefully I'm
missing something
I don't see why you think that's an ugly hack.

def printitems(sequence, count=5):
"""Print count items of sequence per line."""
numrows = len(sequence)//count
if len(sequence)%count != 0: numrows += 1
for start in range(0, numrows):
items = sequence[start*count:(start+1)*count]
for item in items:
print item,
print

Ugliness is in the eye of the beholder.
It is more blessed to add than to multiply.
Gaze upon this alternative:

def printitems2(sequence, count=5):
"""Print count items of sequence per line."""
for pos in range(0, len(sequence), count):
for item in sequence[pos:pos+count]:
print item,
print

Cheers,
John
Very nice.

~Simon

Aug 16 '06 #9
On 15 Aug 2006 18:33:51 -0700,
"John Machin" <sj******@lexicon.netwrote:
Dan Sommers wrote:
>>
counter = 0
for an_element in the_list:
print an_element,
counter = counter + 1
if counter == n:
print
counter = 0
Yes, often simple old-fashioned ways are the best. A little verbose,
though. And I'd do some old-fashioned testing -- the above needs "if
counter: print" after the loop has finished, to get the final '\n' for
cases where there are not an even multiple of n elements.
I know I *thought* "untested"; I could have sworn that I typed it, too.
Sorry.

OTOH, pasted directly from my interactive python session (I changed
sys.ps2 to four spaces to make pasting from these sessions into an
editor that much easier):

Python 2.4.2 (#1, Jun 17 2006, 00:09:19)
[GCC 4.0.1 (Apple Computer, Inc. build 5247)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>c = 0
for e in range(10):
print e,
c = c + 1
if c == 3:
print
c = 0

0 1 2
3 4 5
6 7 8
9
>>>
And pasted right from an xterm:

$ python -c 'print 3,'
3
$

(All of which only explains your more complex test harness, and I still
should have looked more carefully before I posted.)
... ctr = (ctr + 1) % n
I'm old enough to remember the days when we avoided division like the
plague. Remember those zippy 1MHz (yes, that's an M and not a G) CPUs
with less than a handful of 8-bit registers? Old habits die hard. ;-)

Regards,
Dan

--
Dan Sommers
<http://www.tombstonezero.net/dan/>
"I wish people would die in alphabetical order." -- My wife, the genealogist
Aug 16 '06 #10
On Tue, 15 Aug 2006 19:49:17 -0700, John Machin wrote:
Ugliness is in the eye of the beholder.
It is more blessed to add than to multiply.
Gaze upon this alternative:

def printitems2(sequence, count=5):
"""Print count items of sequence per line."""
for pos in range(0, len(sequence), count):
for item in sequence[pos:pos+count]:
print item,
print

You know, that's so obvious that I've just slapped myself for not thinking
of it first. What *was* I thinking???
--
Steven D'Aprano

Aug 16 '06 #11

Dan Sommers wrote:
On 15 Aug 2006 18:33:51 -0700,
"John Machin" <sj******@lexicon.netwrote:
... ctr = (ctr + 1) % n

I'm old enough to remember the days when we avoided division like the
plague. Remember those zippy 1MHz (yes, that's an M and not a G) CPUs
with less than a handful of 8-bit registers? Old habits die hard. ;-)
How did you avoid division when testing for leap year?

Aug 16 '06 #12

unexpected wrote:
If have a list from 1 to 100, what's the easiest, most elegant way to
print them out, so that there are only n elements per line.

So if n=5, the printed list would look like:

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
etc.

My search through the previous posts yields methods to print all the
values of the list on a single line, but that's not what I want. I feel
like there is an easy, pretty way to do this. I think it's possible to
hack it up using while loops and some ugly slicing, but hopefully I'm
missing something
just variations on previous answers:

rng = range(1,101)

#ad hoc
for line in ( rng[i:i+5] for i in xrange(0,100,5) ):
print ' '.join(map(str,line))

#in general
def lines( seq, count=1 ):
n = len(seq)
for x in ( seq[i:i+count] for i in xrange(0,n,count) ):
yield x

for line in lines( rng, 5 ):
print ' '.join(map(str,line))

Gerard

Aug 16 '06 #13

Gerard Flanagan wrote:
>
just variations on previous answers:

rng = range(1,101)

#ad hoc
for line in ( rng[i:i+5] for i in xrange(0,100,5) ):
print ' '.join(map(str,line))

#in general
def lines( seq, count=1 ):
n = len(seq)
for x in ( seq[i:i+count] for i in xrange(0,n,count) ):
yield x
Don't those last two lines deflate to:
for i in xrange(0,n,count):
yield seq[i:i+count]
???

Aug 16 '06 #14

John Machin wrote:
Gerard Flanagan wrote:

just variations on previous answers:

rng = range(1,101)

#ad hoc
for line in ( rng[i:i+5] for i in xrange(0,100,5) ):
print ' '.join(map(str,line))

#in general
def lines( seq, count=1 ):
n = len(seq)
for x in ( seq[i:i+count] for i in xrange(0,n,count) ):
yield x

Don't those last two lines deflate to:
for i in xrange(0,n,count):
yield seq[i:i+count]
???
Yes! Thank you. (pre-caffeine...)

Gerard

Aug 16 '06 #15
In article <m2************@unique.fqdn>, Dan Sommers <me@privacy.netwrote:
>Perhaps not the prettiest, but I can't think of anything simpler to read
six months from now:

counter = 0
for an_element in the_list:
print an_element,
counter = counter + 1
if counter == n:
print
counter = 0
for counter, an_element in enumerate(the_list):
print an_element,
if not (counter+1) % n:
print
# Plus the final print fixed in an earlier follow-up:
if len(the_list) % n:
print

--
\S -- si***@chiark.greenend.org.uk -- http://www.chaos.org.uk/~sion/
___ | "Frankly I have no feelings towards penguins one way or the other"
\X/ | -- Arthur C. Clarke
her nu becomež se bera eadward ofdun hlęddre heafdes bęce bump bump bump
Aug 16 '06 #16

Yu-Xi Lim wrote:
John Machin wrote:
How did you avoid division when testing for leap year?

Well, you're testing for a modulus, not really a division, so a nasty hack:

def isleapyear(year):
return not year&3

works for 1901-2099.

But programming like this causes all kinds of problems in future. Let's
just hope there aren't too many 1MHz 8-bit computers left by then.
No, I meant a wider range, at least 1 <= year <= 9999. And it's not
only 1MHz 8-bit computers where non-nasty division/modulus avoidance
hacks can come in handy -- IIRC the millicode for the 32-bit HP PA-RISC
architecture takes 32 divide-step instructions to do an unsigned 32-bit
division. Division is intrinsically relatively slow on most boxes, but
division by a non-power-of-2 constant can be sped up, and so can "x %
constant == 0".

Cheers,
John

Aug 16 '06 #17
unexpected wrote:
If have a list from 1 to 100, what's the easiest, most elegant way to
print them out, so that there are only n elements per line.

So if n=5, the printed list would look like:

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
etc.

My search through the previous posts yields methods to print all the
values of the list on a single line, but that's not what I want. I feel
like there is an easy, pretty way to do this. I think it's possible to
hack it up using while loops and some ugly slicing, but hopefully I'm
missing something
I suppose 'elegance' is in the eye of the beholder. I agree with the
previous posts, a readable for loop is probably the best way to go.
I've instead chosen to use the functional paradigm. I thought someone
might appreciate this:

p = sys.stdout.write
map(p,[str(i)+("\n"+" "*(n-1))[i%n] for i in range(1,101)])

Aug 16 '06 #18

Matimus wrote:
unexpected wrote:
If have a list from 1 to 100, what's the easiest, most elegant way to
print them out, so that there are only n elements per line.

So if n=5, the printed list would look like:

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
etc.

My search through the previous posts yields methods to print all the
values of the list on a single line, but that's not what I want. I feel
like there is an easy, pretty way to do this. I think it's possible to
hack it up using while loops and some ugly slicing, but hopefully I'm
missing something

I suppose 'elegance' is in the eye of the beholder. I agree with the
previous posts, a readable for loop is probably the best way to go.
I've instead chosen to use the functional paradigm. I thought someone
might appreciate this:

p = sys.stdout.write
map(p,[str(i)+("\n"+" "*(n-1))[i%n] for i in range(1,101)])
At least three strikes:

1. The functional paradigm AFAIK abjures side effects.

|>>n = 3
|>>map(p,[str(i)+("\n"+" "*(n-1))[i%n] for i in range(1,11)])
1 2 3
4 5 6
7 8 9
10 [None, None, None, None, None, None, None, None, None, None]

If you want functional, instead of
map(sys.stdout.write, strings)
do this:
sys.stdout.write(''.join(strings))

2. This little gem
("\n"+" "*(n-1))[i%n]
is better written
" \n"[i%n==0]

3. Like some other attempts, it's missing the trailing \n when len(seq)
% n != 0

4. It needs elaboration so that it works with any sequence, not just
range(1, size+1)

Yer out!

Cheers,
John

Aug 16 '06 #19
John Machin wrote:
Matimus wrote:
unexpected wrote:
If have a list from 1 to 100, what's the easiest, most elegant way to
print them out, so that there are only n elements per line.
>
So if n=5, the printed list would look like:
>
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
etc.
>
My search through the previous posts yields methods to print all the
values of the list on a single line, but that's not what I want. I feel
like there is an easy, pretty way to do this. I think it's possible to
hack it up using while loops and some ugly slicing, but hopefully I'm
missing something
I suppose 'elegance' is in the eye of the beholder. I agree with the
previous posts, a readable for loop is probably the best way to go.
I've instead chosen to use the functional paradigm. I thought someone
might appreciate this:

p = sys.stdout.write
map(p,[str(i)+("\n"+" "*(n-1))[i%n] for i in range(1,101)])

At least three strikes:

1. The functional paradigm AFAIK abjures side effects.

|>>n = 3
|>>map(p,[str(i)+("\n"+" "*(n-1))[i%n] for i in range(1,11)])
1 2 3
4 5 6
7 8 9
10 [None, None, None, None, None, None, None, None, None, None]

If you want functional, instead of
map(sys.stdout.write, strings)
do this:
sys.stdout.write(''.join(strings))

2. This little gem
("\n"+" "*(n-1))[i%n]
is better written
" \n"[i%n==0]

3. Like some other attempts, it's missing the trailing \n when len(seq)
% n != 0

4. It needs elaboration so that it works with any sequence, not just
range(1, size+1)

Yer out!

Cheers,
John
Well, I have another at bat, so I will try to redeem myself... using
recursion:

def printTable(l,c):
print(("%d "*len(l[:c]))%tuple(l[:c]))
if( len(l[:c]) 0 ):
printTable(l[c:],c)

printTable(range(1,101),5)

Aug 17 '06 #20
def perline(n):
count = 1
while 1:
yield (count == n) and "\n" or " "
count = count % n + 1

r = range(1,101)
p = perline(5)

print "".join("%d%s" % (x, p.next()) for x in r)

unexpected wrote:
If have a list from 1 to 100, what's the easiest, most elegant way to
print them out, so that there are only n elements per line.

So if n=5, the printed list would look like:

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
etc.

My search through the previous posts yields methods to print all the
values of the list on a single line, but that's not what I want. I feel
like there is an easy, pretty way to do this. I think it's possible to
hack it up using while loops and some ugly slicing, but hopefully I'm
missing something
Aug 17 '06 #21

Matimus wrote:
Well, I have another at bat, so I will try to redeem myself... using
recursion:

def printTable(l,c):
print(("%d "*len(l[:c]))%tuple(l[:c]))
if( len(l[:c]) 0 ):
printTable(l[c:],c)

printTable(range(1,101),5)
Sorry. Recursion disqualified your batter before he got out of the
dugout. Besides the %d restricts it to use wirh integers, and using
"L".lower() as a variable name made the umpire barf through his
facemask all over the catcher. Fortunately the ump didn't notice the
weirdly-spaced and superfluous () in the if statement ...

Aug 17 '06 #22
On 2006-08-15, unexpected <su***********@gmail.comwrote:
If have a list from 1 to 100, what's the easiest, most elegant
way to print them out, so that there are only n elements per
line.

So if n=5, the printed list would look like:

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
etc.

My search through the previous posts yields methods to print
all the values of the list on a single line, but that's not
what I want. I feel like there is an easy, pretty way to do
this. I think it's possible to hack it up using while loops and
some ugly slicing, but hopefully I'm missing something
I can't resist putting in my oar:

def print_per(seq, n, isep=" ", rsep="\n"):
"""Print the items in seq, splitting into records of length n.

Trailing records may be shorter than length n."""
t = len(seq)
for i in xrange(n, t+1, n):
print isep.join(map(str, seq[i-n:i]))+rsep,
t = t % n
if t 0:
print isep.join(map(str, seq[-t:]))+rsep,

That's probably similar to some of the other mostly
non-functional solutions posted.

--
Neil Cerutti
Aug 17 '06 #23
unexpected wrote:
If have a list from 1 to 100, what's the easiest, most elegant way to
print them out, so that there are only n elements per line.
I've run into this problem a few times, and although many solutions
have been presented specifically for printing I would like to present a
more general alternative.

from itertools import chain
def istepline(step, iterator):
i = 0
while i < step:
yield iterator.next()
i += 1

def istep(iterable, step):
iterator = iter(iterable) # Make sure we won't restart iteration
while True:
# We rely on istepline()'s side-effect of progressing the
# iterator.
start = iterator.next()
rest = istepline(step - 1, iterator)
yield chain((start,), rest)
for i in rest:
pass # Exhaust rest to make sure the iterator has
# progressed properly.
>>i = istep(range(12), 5)
for x in i: print list(x)
....
[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[10, 11]
>>i = istep(range(12), 5)
for x in i: print x
....
<itertools.chain object at 0xa7d3268c>
<itertools.chain object at 0xa7d3260c>
<itertools.chain object at 0xa7d3266c>
>>from itertools import islice, chain, repeat
def pad(iterable, n, pad): return islice(chain(iterable, repeat(pad)), n)
i = istep(range(12), 5)
for x in i: print list(pad(x, 5, None))
....
[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[10, 11, None, None, None]

Would anybody else find this useful? Maybe worth adding it to itertool?

Aug 19 '06 #24
Rhamphoryncus wrote:
I've run into this problem a few times, and although many solutions
have been presented specifically for printing I would like to present a
more general alternative.
[snip interesting istep function]
Would anybody else find this useful? Maybe worth adding it to itertool?
yeah, but why on earth did you make it so complicated?

def istep(iterable, step):
a=[]
for x in iterable:
if len(a) >= step:
yield a
a=[]
a.append(x)
if a:
yield a

--
- Justin

Aug 21 '06 #25
In <11*********************@p79g2000cwp.googlegroups. com>, Justin Azoff
wrote:
Rhamphoryncus wrote:
[snip interesting istep function]
>Would anybody else find this useful? Maybe worth adding it to itertool?

yeah, but why on earth did you make it so complicated?

def istep(iterable, step):
a=[]
for x in iterable:
if len(a) >= step:
yield a
a=[]
a.append(x)
if a:
yield a
This is not as "lazy" as Rhamphoryncus' function anymore. Lets say the
`iterable` is a stream of events, then your function always needs to
"receive" `step` events before the caller can do anything else with the
events. In Rhamphoryncus' function the caller can react on the event as
soon as it's "delivered" by `iterable`.

Ciao,
Marc 'BlackJack' Rintsch
Aug 21 '06 #26
On 2006-08-19, Rhamphoryncus <rh****@gmail.comwrote:
unexpected wrote:
>If have a list from 1 to 100, what's the easiest, most elegant
way to print them out, so that there are only n elements per
line.

I've run into this problem a few times, and although many
solutions have been presented specifically for printing I would
like to present a more general alternative.

from itertools import chain
def istepline(step, iterator):
i = 0
while i < step:
yield iterator.next()
i += 1

def istep(iterable, step):
iterator = iter(iterable) # Make sure we won't restart iteration
while True:
# We rely on istepline()'s side-effect of progressing the
# iterator.
start = iterator.next()
rest = istepline(step - 1, iterator)
yield chain((start,), rest)
for i in rest:
pass # Exhaust rest to make sure the iterator has
# progressed properly.

Would anybody else find this useful? Maybe worth adding it to
itertool?
Your note me curious enough to re-read the itertools
documentation, and I found the following in 5.16.3 Recipes:

def grouper(n, iterable, padvalue=None):
"grouper(3, 'abcdefg', 'x') --('a','b','c'), ('d','e','f'), ('g','x','x')"
return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)

Wish I'd found that yesterday. ;)

--
Neil Cerutti
Aug 21 '06 #27

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by beliavsky | last post: by
12 posts views Thread by Stanimir Stamenkov | last post: by
5 posts views Thread by micklee74 | last post: by
3 posts views Thread by Muhammad Ahsin Saleem | last post: by
6 posts views Thread by Tekkaman | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.