Johnny
Johnny

Reputation: 512

loop through a list and use previous elements

I have a list that contains decimal numbers, however in this example I use ints:

my_list = [40, 60, 100, 240, ...]

I want to print each element of the list in reverse order and afterwards I want to print a second line where every value is divided by 2, then a third line where the previous int is devided by 3 and so on...

Output should be:

240     120     60     36
120      60     30     18  #previous number divided by 2
 40      20     10      6  #previous number divided by 3
...     ...     ...    ... #previous number divided by 4 ...

My solution is ugly: I can make a slice and reverse that list and make n for loops and append the result in a new list. But there must be a better way. How would you do that?

Upvotes: 1

Views: 224

Answers (5)

FMc
FMc

Reputation: 42411

max_n = 3
vals  = [40, 60, 100, 240]
grid  = [list(reversed(vals))]

for n in xrange(2, max_n + 1):
    grid.append([v/n for v in grid[-1]])

for g in grid:
    print g

# Output
[240, 100, 60, 40]
[120.0, 50.0, 30.0, 20.0]
[40.0, 16.666666666666668, 10.0, 6.666666666666667]

Upvotes: 1

mgilson
mgilson

Reputation: 309841

I'd write a generator to yield lists in turn:

def divider(lst,n):
    lst = [float(x) for x in lst[::-1]]
    for i in range(1,n+1):
        lst = [x/i for x in lst]
        yield lst

is more appropriate. If we want to make it slightly more efficient, we could factor out the first iteration (division by 1) and yield it separately:

def divider(lst,n):
    lst = [float(x) for x in reversed(lst)]
    yield lst
    for i in range(2,n+1):
        lst = [x/i for x in lst]
        yield lst

*Note that in this context there isn't a whole lot of difference between lst[::-1] and reversed(lst). The former is typically a little faster, but the latter is a little more memory efficient. Choose according to your constraints.


Demo:

>>> def divider(lst,n):
...     lst = [float(x) for x in reversed(lst)]
...     yield lst
...     for i in range(2,n+1):
...         lst = [x/i for x in lst]
...         yield lst
... 
>>> for lst in divider([40, 60, 100, 240],3):
...     print lst
... 
[240.0, 100.0, 60.0, 40.0]
[120.0, 50.0, 30.0, 20.0]
[40.0, 16.666666666666668, 10.0, 6.666666666666667]

Upvotes: 4

Mp0int
Mp0int

Reputation: 18727

new_list = my_list[::-1] #reverse the list
print '\t'.join(map(str, new_list))
for _counter in range(2, 21): #count from 2 to 20
    for _index in range(len(new_list)): # iterate the whole list
        new_list[_index] = new_list[_index]/_counter
        print '\t'.join(map(str, new_list))

Which will produce an output like(I used float instead of int):

240.0       100.0         60.0         40.0
120.0        50.0         30.0         20.0
40.0        16.6666666667 10.0         6.66666666667
10.0        4.16666666667 2.5          1.66666666667
2.0         0.833333333333 0.5         0.333333333333

Upvotes: 0

HennyH
HennyH

Reputation: 7944

my_list = [40, 60, 100, 240]
def dostuff(l,limit):
    print('\t'.join(map(str,reversed(l))))
    print('\n'.join([ '\t'.join(map(str,[v/float(i) for v in reversed(my_list)])) for i in range(2,limit+1)]))
dostuff(my_list,20)

Produces:

240 100 60  40
120.0   50.0    30.0    20.0
80.0    33.333333333333336  20.0    13.333333333333334
60.0    25.0    15.0    10.0
48.0    20.0    12.0    8.0
40.0    16.666666666666668  10.0    6.666666666666667
34.285714285714285  14.285714285714286  8.571428571428571   5.714285714285714
30.0    12.5    7.5 5.0
26.666666666666668  11.11111111111111   6.666666666666667   4.444444444444445
24.0    10.0    6.0 4.0
21.818181818181817  9.090909090909092   5.454545454545454   3.6363636363636362
20.0    8.333333333333334   5.0 3.3333333333333335
18.46153846153846   7.6923076923076925  4.615384615384615   3.076923076923077
17.142857142857142  7.142857142857143   4.285714285714286   2.857142857142857
16.0    6.666666666666667   4.0 2.6666666666666665
15.0    6.25    3.75    2.5
14.117647058823529  5.882352941176471   3.5294117647058822  2.3529411764705883
13.333333333333334  5.555555555555555   3.3333333333333335  2.2222222222222223
12.631578947368421  5.2631578947368425  3.1578947368421053  2.1052631578947367
12.0    5.0 3.0 2.0

Upvotes: -2

Francis Avila
Francis Avila

Reputation: 31621

To print the columnar the output you want, use format strings. You may have to tweak this to get the alignment and precision you want for your actual data:

def print_list(L):
    print '    '.join('{:>3d}'.format(i) for i in L)

Normally to do the division we could use a function with recursion, but we can also use a simple loop where each iteration produces the list that is worked on next:

my_list = [40, 60, 100, 240, 36, 60, 120, 240]

maxdiv = 20
baselist = list(reversed(my_list))
for div in range(1, maxdiv+1):
    baselist = [i/div for i in baselist]
    print_list(baselist)

Output:

240    120     60     36    240    100     60     40
120     60     30     18    120     50     30     20
 40     20     10      6     40     16     10      6
 10      5      2      1     10      4      2      1
  2      1      0      0      2      0      0      0
  0      0      0      0      0      0      0      0
  0      0      0      0      0      0      0      0
  0      0      0      0      0      0      0      0
...

Upvotes: 2

Related Questions