2

I am trying to create a list using nested for loops in python. This list needs to be composed of a number of lists, each corresponding to a value of a certain parameter and containing the results of equation for that parameter. Running my code produces an IndexError. This is the part of my code which is causing the problem:

T_1 = [[]]

for j in range(len(A_1)):
        for i in range(len(y_1)):
             T_1[j][i] = T0_1 + ((q0_1 / k_1) * y_1[i]) - ((A_1[j] / (2 * k_1)) * y_1[i]**2)

The sequences A_1 and y_1 are of different size (y_1 is a 150 long list of depth points, A_1 is a 4 character long list of different values of the parameter A).

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
user3046814
  • 33
  • 1
  • 3
  • 1
    Python calls these 'lists'; an `array` is something different (containing values of just one type, see the `array` module in Python). – Martijn Pieters Nov 28 '13 at 17:26

3 Answers3

2

Python lists don't grow automatically; addressing indexes that don't exist does not work. You'd normally use .append() for that:

T_1 = []

for a in A_1:
    nested = []
    T_1.append(nested) 
    for y in y_1:
        nested.append(T0_1 + ((q0_1 / k_1) * y) - (a / (2 * k_1)) * y**2))

Note that you don't need to create indices anymore; you can loop directly over A_1 and y_1 and use the values in the formula.

The alternative would be to create an empty structure with placeholder values; like None:

T_1 = [[None] * len(y_1) for _ in range(len(A_1))]

for i, a in enumerate(A_1):
    for j, y in enumerate(y_1):
        T_1[i][j] = T0_1 + ((q0_1 / k_1) * y) - (a / (2 * k_1)) * y**2))

Here I used enumerate() to add an index to each loop; this lets you have your cake and eat it; access a value from an input sequence and its location in the sequence.

However, your nested lists can most simply be generated with a nested set of list comprehensions:

T_1 = [[T0_1 + ((q0_1 / k_1) * y) - ((a / (2 * k_1)) * y**2) for i in y_1] for a in A_1]

Here [expression for variable in iterable] executes the expression on the left-hand side for each iteration of the loop. The outer loop over A_1 generates a new list for each a in the loop. That new list is itself a list comprehension, looping over y_1 and generating new values (your formula) for each element.

Note that now we no longer need to generate indices or use list.append() each loop iteration. The lists are built in-place.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
1
T_1 = [[T0_1 + ((q0_1 / k_1) * y_1[i]) - ((A_1[j] / (2 * k_1)) * y_1[i]**2) for j in range(len(A_1))] for i in range(len(y_1))]
alinsoar
  • 15,386
  • 4
  • 57
  • 74
  • Why use `range(len(y_1))` and `range(len(A_1))` when all you use `i` and `j` for is indexing into `y_1` and `A_1`? Why not loop directly over those sequences instead? – Martijn Pieters Nov 28 '13 at 18:22
  • yeah, I gave the fast answer, copy-paste... `for x in A_1` and x instead of `A_1[j]`. – alinsoar Nov 28 '13 at 21:04
0

Short answer

T_1 = []  # outer list, all rows
for j in range(len(A_1)):
    T_1.append( [] )  # new inner list, a row
    for i in range(len(y_1)):
        # last row is T_1[-1] and you append to it
        your_value = T0_1 + ((q0_1 / k_1) * y_1[i]) - ((A_1[j] / (2 * k_1)) * y_1[i]**2)
        T_1[-1].append(your_value)

Reference

L = [ [1, 2, 3],
      [4, 5, 6],
      [7, 8, 9] ]

L[0]  -> [1, 2, 3]
L[1]  -> [4, 5, 6]
L[2]  -> [7, 8, 9]
L[-1] -> [7, 8, 9]

L[0][0] -> 1
L[1][0] -> 4
L[-1][-1] -> 9

You may want to do it via list comprehension.
Don't even try at this point.
Because you will make a lot of mistakes.

akaRem
  • 7,326
  • 4
  • 29
  • 43