Mickey Mahoney
Mickey Mahoney

Reputation: 381

difference between range / len etc. when iterating over tuples

One thing upfront: I am fairly now to the coding world so maybe my question is a bit stupid ... I was trying to write a function that returns the every other element of a tuple. The easiest way obviously is

def oddTuples(aTup):
     return aTup[::2]

I tried to solve it differently by using the following code

def oddTuples(aTup):
    newTup = ()
    for i in len(aTup):
        if i%2 != 0:
            newTup = newTup + (i,)
    return newTup

But that doesn't give me back anything at all.

I thought I (if used over len) gives back the position, so if aTup = ((12, 34, 'abc', 'dfdf', 2340)) the return would be newTup = ((12, 'abc', 2340)).

What's the i iterating over when used with range, len or -in that case- while iterating over for i in aTup:?

Upvotes: 1

Views: 5724

Answers (5)

Martijn Pieters
Martijn Pieters

Reputation: 1122092

Python's for loop is a foreach construct; it'll loop over a sequence or iterable and bind the target variable (i in your case) to each element in that sequence one by one.

So for for i in aTuple:, with each iteration, i is bound to the next value from the tuple. If you used a range() object, then looping over that object would produce integers in the range, from start (defaulting to 0) up to the end value minus 1 (the end value is excluded).

Your code, however, doesn't loop over range(); you try to loop over the result of len(aTuple), which will be a single integer. That gives a TypeError: 'int' object is not iterable exception.

If you want to use the range() type, that's fine, but then you'll have to translate the index back into a value from aTuple by using indexing:

def oddTuples(aTup):
    newTup = ()
    for i in range(len(aTup)):
        if i%2 != 0:
            newTup = newTup + (aTup[i],)
    return newTup

Here aTup[i] produces the value at index i; where i is so index 1, 3, etc, so you get every odd element. Note that this differs from aTup[::2], which starts at 0 and includes every even-numbered element! Python starts counting at 0, so take that into account when counting out elements.

You can avoid having to index back in by using the enumerate() function; for every element in a sequence it'll produce a tuple with an ever-increasing index number. Let's use that to fix the odd-even issue, mixing in some += augmented assignment too:

def oddTuples(aTup):
    newTup = ()
    for i, value in enumerate(aTup):
        if i % 2 == 0:
            newTup += value,
    return newTup

You don't really need the (...) parentheses here either, tuples are formed by commas (except for the empty tuple, and use parentheses when the comma could mean something else, like in a function call).

Upvotes: 3

Maddy
Maddy

Reputation: 2060

Here is an example you can use to finish the program.

myTup = (1,2,3,4,5,6,7,8)

for i in range(len(myTup)):
    if i%2 != 0:
        print("Tuple items: " ,myTup[i])
        print("i here is: " , i)

len -> gives you the length of a object ; eg. if you say len(myTup). That will be 8

Range -> is like a range, (number of elements) you will be iterating over.

i -> is the index.

Here is the output

Tuple items:  2
i here is:  1
Tuple items:  4
i here is:  3
Tuple items:  6
i here is:  5
Tuple items:  8
i here is:  7

You can get the same output above by running the code without using range and len.

for i in myTup:
    if i%2 != 0:
        print("Tuple items: " ,myTup[i])
        print("i here is: " , i)

Upvotes: 0

mkreddy
mkreddy

Reputation: 163

The i will not give you the index instead it will return the value.

You can solve your problem simply by defining a local variable that can be incriminated for each iteration and use that to get the odd indexed values.

Summery: Use a local variable to act as an index as Python for will return the value.

Upvotes: 0

elethan
elethan

Reputation: 16993

for i in len(aTup):

Will raise an error because len() returns an integer which can not be iterated over in a for loop.

In the case of:

for i in range(len(aTup)):

In each iteration of the loop i will be an integer starting from 0 and up to the length of your tuple - 1.

In the case of:

for i in aTup:

Each i will be a member of the tuple. The best way to get used to how these things work is to just pop open an interactive interpreter and do some experiments!

>>> aTup = ('hello', 'world')
>>> for i in len(aTup):
...     print i
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>> for i in range(len(aTup)):
...     print i
... 
0
1
>>> for i in aTup:
...     print i
... 
hello
world
>>> 

Upvotes: 0

Patrick Haugh
Patrick Haugh

Reputation: 60994

newTup = ()
b = True
for i in aTup:
    if b:
        newTup = newTup + (i,)
    b = not b
return newTup

Try that on for size. The for statement gives us the tuple values one by one, and the boolean b lets us skip every other one.

The best way to do this is the way you put at the top of your post. If you don't understand what it's doing, then I suggest researching list slicing.

Upvotes: 0

Related Questions