205

I need to code such that if a certain list index exists, then run a function.

My failing code:

n = int(input("Define number of actors: "))
count = 0
nams = []
while count < n:
    count = count + 1
    print("Define name for actor", count, ":")
    nams.append(input())
if nams[2]:  # 'if nams[2] exists, do something depending on len(nams)
    if len(nams) > 3:
        do_something
0

11 Answers 11

219

Could it be more useful for you to use the length of the list len(nams) to inform your decision rather than checking nams[i] for each possible length?

Sign up to request clarification or add additional context in comments.

3 Comments

Yep. Upon reviewing the code, my set-up was completely superfluous; len(n) accomplished everything I needed. Thanks for a point in the right direction.
This doesn't account for negative indexes. The best way I know is try / except IndexError, but it'd be nice to have a concise way to get a bool
In Python negative indexes on lists just count backwards from the end of the list. So they could not exist in a way that impacts the length of the list.
120

I need to code such that if a certain list index exists, then run a function.

This is the perfect use for a try block:

ar=[1,2,3]

try:
    t=ar[5]
except IndexError:
    print('sorry, no 5')   

# Note: this only is a valid test in this context 
# with absolute (ie, positive) index
# a relative index is only showing you that a value can be returned
# from that relative index from the end of the list...

However, by definition, all items in a Python list between 0 and len(the_list)-1 exist (i.e., there is no need for a try block if you know 0 <= index < len(the_list)).

You can use enumerate if you want the indexes between 0 and the last element:

names=['barney','fred','dino']

for i, name in enumerate(names):
    print(i + ' ' + name)
    if i in (3,4):
        # do your thing with the index 'i' or value 'name' for each item...

If you are looking for some defined 'index' though, I think you are asking the wrong question. Perhaps you should consider using a mapping container (such as a dict) versus a sequence container (such as a list). You could rewrite your code like this:

def do_something(name):
    print('some thing 1 done with ' + name)
        
def do_something_else(name):
    print('something 2 done with ' + name)        
    
def default(name):
    print('nothing done with ' + name)     
    
something_to_do={  
    3: do_something,        
    4: do_something_else
    }        
            
n = input ("Define number of actors: ")
count = 0
names = []

for count in range(n):
    print("Define name for actor {}:".format(count+1))
    name = raw_input ()
    names.append(name)
    
for name in names:
    try:
        something_to_do[len(name)](name)
    except KeyError:
        default(name)

Runs like this:

Define number of actors: 3
Define name for actor 1: bob
Define name for actor 2: tony
Define name for actor 3: alice
some thing 1 done with bob
something 2 done with tony
nothing done with alice

You can also use .get method rather than try/except for a shorter version:

>>> something_to_do.get(3, default)('bob')
some thing 1 done with bob
>>> something_to_do.get(22, default)('alice')
nothing done with alice

8 Comments

try block? I am a beginner in Python but this seems like a big no no in programming...exceptions for flow control? Exception should be for things we cannot control right?
@Luis I'm a beginner in Python as well, but from what I've read exception handling in these instances is the style Python promotes that C/Java/C# don't. See stackoverflow.com/questions/11360858/…
The sentence 'all indices in a Python list between 0 and len(list)' is absolutely wrong. Let's say there's a list x = [1, 2, 3] which len_x = 3. There is no such index as 3. The sentence should have been: 'all indices in a Python list between 0 and len(list) - 1'.
I'll point out that sticking things inside a try does not tell you if the index exists just if it is fetchable - take -1 - that index doesn't really exist but a value would be returned.
Hmm I have the rep to just edit, but that seems rude. I would say something like *Note* that this approach will work whenever a value *can be looked up* by a specific index from the list. This is not quite the same as if an index exists. You can for example fetch the value at -1 (the last item) but that index does not exist. To check if an index exists use 0 <= n < len(lst)
|
28

It can be done simply using the following code:

if index < len(my_list):
    print(index, 'exists in the list')
else:
    print(index, "doesn't exist in the list")

1 Comment

And if index is -1 to indicate the last item? That should fail for empty lists, but doesn't here...
22

len(nams) should be equal to n in your code. All indexes 0 <= i < n "exist".

Comments

8

I need to code such that if a certain list index exists, then run a function.

You already know how to test for this and in fact are already performing such tests in your code.

The valid indices for a list of length n are 0 through n-1 inclusive.

Thus, a list has an index i if and only if the length of the list is at least i + 1.

2 Comments

Yep, I had the tools to solve my problem, just wasn't applying them clearly. Thanks for a point in the right direction.
Thanks for this, especially the last sentence, which is an important property of Python lists that make them different from JavaScript arrays and other similar constructs.
8

Using the length of the list would be the fastest solution to check if an index exists:

def index_exists(ls, i):
    return (0 <= i < len(ls)) or (-len(ls) <= i < 0)

This also tests for negative indices, and most sequence types (Like ranges and strs) that have a length.

If you need to access the item at that index afterwards anyways, it is easier to ask forgiveness than permission, and it is also faster and more Pythonic. Use try: except:.

try:
    item = ls[i]
    # Do something with item
except IndexError:
    # Do something without the item

This would be as opposed to:

if index_exists(ls, i):
    item = ls[i]
    # Do something with item
else:
    # Do something without the item

Comments

2

If you want to iterate the inserted actors data:

for i in range(n):
    if len(nams[i]) > 3:
        do_something
    if len(nams[i]) > 4:
        do_something_else

Comments

0

ok, so I think it's actually possible (for the sake of argument):

>>> your_list = [5,6,7]
>>> 2 in zip(*enumerate(your_list))[0]
True
>>> 3 in zip(*enumerate(your_list))[0]
False

2 Comments

though this would be even simpler: 3 in range(len(your_list)
or even this 3 in xrange(len(your_list) - probably can't do better than this
0

You can try something like this

list = ["a", "b", "C", "d", "e", "f", "r"]

for i in range(0, len(list), 2):
    print list[i]
    if len(list) % 2 == 1 and  i == len(list)-1:
        break
    print list[i+1];

Comments

0

Oneliner:

do_X() if len(your_list) > your_index else do_something_else()  

Full example:

In [10]: def do_X(): 
    ...:     print(1) 
    ...:                                                                                                                                                                                                                                      

In [11]: def do_something_else(): 
    ...:     print(2) 
    ...:                                                                                                                                                                                                                                      

In [12]: your_index = 2                                                                                                                                                                                                                       

In [13]: your_list = [1,2,3]                                                                                                                                                                                                                  

In [14]: do_X() if len(your_list) > your_index else do_something_else()                                                                                                                                                                      
1

Just for info. Imho, try ... except IndexError is better solution.

Comments

0

Here's a simple, if computationally inefficient way that I felt like solving this problem today:

Just create a list of available indices in my_list with:

indices = [index for index, _val in enumerate(my_list)]

Then you can test before each block of code:

if 1 in indices:
    "do something"
if 2 in indices:
    "do something more"

but anyone reading this should really just take the correct answer from: @user6039980

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.