Marco Leonardi
Marco Leonardi

Reputation: 149

How to iterate on elements of lists within a bigger list?

Python beginner here, I've literally spent several hours of what I assume is a grade school problem to most - but I finally managed to get a solution together.

The assignment was: Given a list of lists, such as L=[[1,2],[2,3,5]] I want to multiply by 5 all the odd numbers in L.

Eventually I came up with this, which miraculously worked:

  def isOdd(n):
    if n%2 != 0:
        return True
    else:
        return False

    
def mult(L):
    for i in L:
        for j in i:
            if isOdd(j):
                oddInd = i.index(j)
                i[oddInd] = j*5
    print(L)

I hardly ever ask for homework help, but I feel okay about this one since I've already done it; the reason I'm writing this here is to know if there's a better and quicker way to get around this (I'm sure it can be done in 2 lines).

Also why wouldn't this work? (It was my first thought, and why I wasted so much time, before thinking about indices)

def mult(L):
  for i in L:
    for j in i:
      if isOdd(j):
        j = j*5

Thank you for your time everyone!

Upvotes: 0

Views: 100

Answers (3)

Buddy Bob
Buddy Bob

Reputation: 5889

Your problem would be that you never actually modify L when iterating over it.

Use list comprehension

L=[[1,2],[2,3,5]]
newL = [[num*5 if num%2 !=0 else num for num in lst] for lst in L]

output

[[5, 2], [2, 15, 25]]

Upvotes: 0

Ares Stavropoulos
Ares Stavropoulos

Reputation: 170

Your first solution was good, but it failed in a couple of cases. If you input [[3,15]], you'll find that your solution outputs [[75,15]]. That's because when you assign the variable oddInd, you say i.index(j). That's an issue because index will only find the first instance of that value, meaning if there are multiple instances of value 'j' in the given list, you may get an undesired output like we saw. A solution is to write the function like this:

def mult(L):
  for i in L:
    for j in range(len(i)):
      if isOdd(i[j]):
        i[j] = i[j]*5
  print(L)

In this solution, we find the length of the list 'i', and loop through that length, so that when we want to find the instance of that index, i[j] will find us that, without any chance of finding an incorrect instance like i.index(j) will. Prune also explained this well, I just wanted to give another solution and perspective

Upvotes: 0

Prune
Prune

Reputation: 77837

Your given solution is almost correct. Try it with a sub-list where a later element is 5 times a previous one, and you'll see a failure. For instance, simply L = [[1, 5]]. The problem is that find locates only the first instance of the value in the list, not the one you reference with j. Instead ...

    for oddIdx, j in enumerate(i):
        if isOdd(j):
            i[oddInd] = j*5

I deleted the rest of my answer, as BubbyBob just covered the list comprehension.

Upvotes: 3

Related Questions