Printing n elements per line in a list

U

unexpected

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
 
P

Paul Rubin

unexpected said:
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.
 
P

Paul Rubin

Paul Rubin said:
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.
 
D

Dan Sommers

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
 
S

Simon Forman

unexpected said:
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
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
 
J

John Machin

Dan said:
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.
.... ctr = 0
.... for item in alist:
.... print item,
.... ctr = (ctr + 1) % n
.... if not ctr:
.... print
.... if ctr:
.... print
........ 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
 
S

Steven D'Aprano

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
 
J

John Machin

Steven said:
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
 
S

Simon Forman

John said:
Steven said:
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
 
D

Dan Sommers

Dan Sommers wrote:
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. 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
 
S

Steven D'Aprano

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???
 
J

John Machin

Dan said:
On 15 Aug 2006 18:33:51 -0700,


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?
 
G

Gerard Flanagan

unexpected said:
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
 
J

John Machin

Gerard said:
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]
???
 
Y

Yu-Xi Lim

John said:
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.
 
G

Gerard Flanagan

John said:
Gerard said:
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
 
S

Sion Arrowsmith

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
 
J

John Machin

Yu-Xi Lim said:
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
 
M

Matimus

unexpected said:
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)])
 
J

John Machin

Matimus said:
unexpected said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top