最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python 3.x - Listing an array of strings into multiple columns vertically - Stack Overflow

programmeradmin3浏览0评论

I'm trying to list multiple columns ordered vertically in the format

A D G

B E H

C F

but I can't figure out how to change it from how I'm currently doing it, which is just ordering it horizontally

A B C

D E F

G H

lines = (' '.join(justifyList[i:i + cols])
             for i in range(0, len(justifyList), cols))
    
return "\n".join(lines)

The size of the list is subject to change as is the number of columns. Is there a way to easily change the formatting?

I'm trying to list multiple columns ordered vertically in the format

A D G

B E H

C F

but I can't figure out how to change it from how I'm currently doing it, which is just ordering it horizontally

A B C

D E F

G H

lines = (' '.join(justifyList[i:i + cols])
             for i in range(0, len(justifyList), cols))
    
return "\n".join(lines)

The size of the list is subject to change as is the number of columns. Is there a way to easily change the formatting?

Share Improve this question asked Jan 19 at 7:22 EcylinEcylin 134 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 0

A feature called slicing can allow you to access a subset of elements in your list. For example,

>>> l = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
>>> l[:2]
['A', 'B']

A less-well known feature of slicing is that you can slice every n elements, much like the hidden third parameter of the range() function. This is what you need to list your items vertically.

>>> l[::3]
['A', 'D', 'G']

Since we do not need access to all the elements simultaneously, we can use iterators. Iterators do not hold references to all elements at the same time, which saves us a little bit of memory. However, as a result, we may iterate through the iterator only once. If multiple iterations are needed, use the slicing syntax above to generate new lists. Here, we can get sliced iterators from the built-in module itertools, using islice().

>>> l = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
>>> from itertools import islice
>>> islice(l, None, None, 3)
<itertools.islice object at 0x00000212CCDE0860>
>>> list(islice(l, None, None, 3))
['A', 'D', 'G']

Mixing everything together with some for loops, we get

from itertools import islice

l = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
n = 3

for i in range(n):
    print(' '.join(islice(l, i, None, n)))

Giving us the result,

A D G
B E H
C F

Finally, with some f-string magic, we can pad every entry to the maximum size.

from itertools import islice, batched

l = ['Apple', 'Banana', 'Cat', 'Dog', 'Elephant', 'Frog', 'Grapes', 'Helicopter']
n = 3

maxsizes = [max(len(e) for e in ll) for ll in batched(l, n)]

for i in range(n):
    print(' '.join(f'{e:<{maxsize}}' for e, maxsize in zip(islice(l, i, None, n), maxsizes)))

Which prints,

Apple  Dog      Grapes    
Banana Elephant Helicopter
Cat    Frog    

Other than readability issues in my code (maybe expand some of the generator expressions haha), a minor issue is that spaces are printed even when they're not needed at the end of a line, but I can't think of a solution of the top of my head, so I'll leave that as an exercise to the reader lol.

EDIT:

ChatGPT-inspired alternative implementation.

from itertools import batched, zip_longest

l = ['Apple', 'Banana', 'Cat', 'Dog', 'Elephant', 'Frog', 'Grapes', 'Helicopter']
n = 3

# Calculate max column widths
col_maxsizes = [max(len(e) for e in col) for col in batched(l, n)]

# Print rows with formatted columns
for row in zip_longest(*batched(l, n), fillvalue=''):
    print(' '.join(f'{e:<{maxsize}}' for e, maxsize in zip(row, col_maxsizes)).strip())

The simpliest way would be to utilize the basics of multi-dimensional arrays. Why?
Notice that the array:

A B C | D E F | G H

May be "inflated" to the shape of a two-dimensional array:

A B C
D E F
G H

The key is to pick the right amount of letters per row (let's call it n). Then, we only need to display every n-th element:

A D G

To display another columns, we need to add two another variables - the column offset (let's call it c) and the row iterator (assume it's r). Now, we use the pattern (r * c) + n.
Below I present a Python script that performs these operations:

import math

t = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
n = 3

column_size = math.ceil(len(t) / n)

table = [[] for _ in range(int(n))]

for c in range(len(table)):
    for r in range (0, n, 1):

        index = n * r + c
        if index >= len(t):
            table[c].append(' ')
        else:
            table[c].append( t[index] )

for row in table:
    print(" ".join(row))

This solution not only provides vertical transposition but also ensures every produced row is coherent with its original column which is done by inserting spaces.

发布评论

评论列表(0)

  1. 暂无评论