Printing n elements per line in a list

M

Matimus

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

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

johnzenger

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

John Machin

Matimus said:
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 ...
 
N

Neil Cerutti

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.
 
R

Rhamphoryncus

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.

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.
....
[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[10, 11]
....
<itertools.chain object at 0xa7d3268c>
<itertools.chain object at 0xa7d3260c>
....
[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?
 
J

Justin Azoff

Rhamphoryncus said:
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
 
M

Marc 'BlackJack' Rintsch

Justin Azoff said:
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
 
N

Neil Cerutti

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. ;)
 

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,780
Messages
2,569,608
Members
45,244
Latest member
cryptotaxsoftware12

Latest Threads

Top