5
\$\begingroup\$

I have a list of strings. I need to list them in rows and columns. Each row should not have more than "cols" number of values. Each of the values in a given row should be "step" away from the previous value. The values should appear only once in the output. Here is what I have. Any better way to write this code?

cols = 4
step = 10
vlist = ["Value" + str(i+1) for i in range(100)]

vlen = len(vlist)
start = 0
while start < vlen and start < step:
    num = 0
    for idx in range(start, vlen, step):
        if num < cols:
            print(vlist[idx], end=", ")
            num += 1
    print("\n")
    start += 1
\$\endgroup\$
  • \$\begingroup\$ Welcome to Code Review! Is Each [value] should be "step" away from the previous value an "external" requirement? ((Block-) Quote the specification of the result to achieve.) Another interpretation is In a monospace font, each value shall be output 10 places to the right of the preceding one, the advantage being all values getting displayed. \$\endgroup\$ – greybeard Mar 16 at 6:33
  • \$\begingroup\$ I don't really understand the problem statement. Could you possibly provide a sample input and the expected output to show what's required? That would really help! \$\endgroup\$ – Toby Speight Mar 18 at 9:38
7
\$\begingroup\$

Fancy iteration in Python is often made easier using the itertools module. For this case, itertools.islice() can help pick out the values for each row.

from itertools import islice

cols = 4
step = 10
vlist = ["Value" + str(i+1) for i in range(100)]

for row in range(step):
    print(', '.join(islice(vlist, row, cols * step, step)), end=", \n\n")
\$\endgroup\$
1
\$\begingroup\$

The code can be made more understandable by:

  • introducing row and column indices
  • replace the while loop with a for loop
  • calculate the index for vlist from the values of the row/col indices

This reduces the number of help variables needed and could result in something like this:

vlist = ["Value" + str(i+1) for i in range(100)]

cols = 4
rows = 10
for row_idx in range(rows):
    for col_idx in range(cols):

        idx = row_idx + rows * col_idx
        print(vlist[idx], end=", ")

    print("\n")
\$\endgroup\$
  • \$\begingroup\$ Thanks Jan. I used this approach as well. But your code looks cleaner :) \$\endgroup\$ – RebornCodeLover Mar 16 at 20:24
1
\$\begingroup\$

It can be solved by using the slice object.

From Python documentation:

slice - An object usually containing a portion of a sequence. A slice is created using the subscript notation, [] with colons between numbers when several are given, such as in variable_name[1:3:5]. The bracket (subscript) notation uses slice objects internally.

cols = 4 
step = 10
vlist = ["Value" + str(i+1) for i in range(100)]

end = step * cols
for start in range(step):
    print(', '.join(vlist[start:end:step]))

Output

Value1, Value11, Value21, Value31
Value2, Value12, Value22, Value32
Value3, Value13, Value23, Value33
Value4, Value14, Value24, Value34
Value5, Value15, Value25, Value35
Value6, Value16, Value26, Value36
Value7, Value17, Value27, Value37
Value8, Value18, Value28, Value38
Value9, Value19, Value29, Value39
Value10, Value20, Value30, Value40
\$\endgroup\$
  • \$\begingroup\$ Thank you @MinMax. 200_success also gave the same answer earlier. \$\endgroup\$ – RebornCodeLover Mar 17 at 14:51
  • \$\begingroup\$ @RebornCodeLover It is different. @200_success uses the islice from itertools. I use built-in slice. But yes, they are similar in other ways. \$\endgroup\$ – MiniMax Mar 17 at 14:56
  • \$\begingroup\$ True. Yes I like it. Thanks \$\endgroup\$ – RebornCodeLover Mar 17 at 14:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.