200

In my program, user inputs number n, and then inputs n number of strings, which get stored in a list.

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

This is made more complicated by the fact that I have nested if statements about len(my_list).

Here's a simplified version of what I have now, which isn't working:

n = input ("Define number of actors: ")

count = 0

nams = []

while count < n:
    count = count + 1
    print "Define name for actor ", count, ":"
    name = raw_input ()
    nams.append(name)

if nams[2]: #I am trying to say 'if nams[2] exists, do something depending on len(nams)
    if len(nams) > 3:
        do_something
    if len(nams) > 4
        do_something_else

if nams[3]: #etc.
user1569317
  • 2,436
  • 3
  • 14
  • 17
  • 1
    Looks like you want to type cast `n` as an integer, not a list. I'm confused. – mVChr Aug 02 '12 at 21:39
  • 2
    Yes, the real problem here is using `n` instead of `nams` in the `if`s – Wooble Aug 02 '12 at 21:48
  • In your case n is not a list. First check (cast) it to be an integer, then you could iterate or enumerate depending on the effect you want to achieve. – laidback Aug 02 '12 at 21:48
  • Yep, mistyped. Fixed to nams[] – user1569317 Aug 02 '12 at 21:56
  • "the fact that I have sub if statements about len(my_list)." Have you thought about what is implied about which list indices exist, by the fact that the `len` of the list is at least a certain value? – Karl Knechtel Aug 02 '12 at 22:45
  • Possible duplicate of [How to check if the n-th element exists in a Python list?](http://stackoverflow.com/questions/15554255/how-to-check-if-the-n-th-element-exists-in-a-python-list) – wedi Apr 09 '17 at 08:57
  • @wedi this question was asked in 2012 that one in 2013, so actually it is the other way around **for others: No, there is no hasIndex/isset in Python for lists** you must go with `len()` or `IndexError` exception checking, not sure why it wasn't implemented straight away, but that's just how things are... refs: https://docs.python.org/3/library/stdtypes.html#mutable-sequence-types https://docs.python.org/3/tutorial/datastructures.html – jave.web Feb 02 '21 at 15:59

12 Answers12

217

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

Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
JonathanV
  • 2,484
  • 1
  • 13
  • 9
  • 7
    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. – user1569317 Aug 03 '12 at 18:37
  • 2
    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 – Abram Aug 06 '19 at 19:55
  • 1
    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. – JonathanV Aug 07 '19 at 18:00
119

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
dawg
  • 98,345
  • 23
  • 131
  • 206
  • 9
    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 Jan 05 '15 at 14:42
  • 3
    @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 http://stackoverflow.com/questions/11360858/what-is-the-eafp-principle-in-python – Tinister Jan 09 '15 at 21:49
  • 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'. – Lior Magen Apr 12 '16 at 10:26
  • 10
    @LiorMagen: You are right and I edited it. That is kinda harsh to down vote a fairly popular post for such a pedantic error. A simple comment would suffice. – dawg Apr 14 '16 at 01:15
  • 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. – George Mauer Oct 27 '19 at 21:33
  • @GeorgeMauer: Point taken, but this is a bit like Clinton's *“It depends on what the meaning of the word ‘is’ is.”* In this context, it depends on the meaning of *exists* and if that meaning is different for relative vs absolute indices. – dawg Oct 28 '19 at 02:06
  • @dawg yup, I'm not downvoting or anything, but do suggest making an edit to explicitly state that. This answer is popping up for "determine if an index is in a list" searches (which is how I ended up here) and depending on what they want, it might introduce a subtle bug that won't be caught easily (again, what happened to me - but not your fault, I found this after *after* I realized the bug) – George Mauer Oct 28 '19 at 02:10
  • @GeorgeMauer: Say more about the specific edit suggested. If edited to clarify that this only applies to positive (non-relative) indices, would that have clarified this for you before your bug? – dawg Oct 28 '19 at 02:48
  • 3
    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)` – George Mauer Oct 28 '19 at 15:09
  • I added a comment to the code example that addresses your comment. Thanks! – dawg Oct 28 '19 at 15:52
27

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")
user6039980
  • 3,108
  • 8
  • 31
  • 57
22

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

jfs
  • 399,953
  • 195
  • 994
  • 1,670
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
Artyer
  • 31,034
  • 3
  • 47
  • 75
7

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.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
  • Yep, I had the tools to solve my problem, just wasn't applying them clearly. Thanks for a point in the right direction. – user1569317 Aug 03 '12 at 18:40
  • 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. – robert Feb 22 '16 at 20:46
3

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
gepatino
  • 160
  • 2
1

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
avloss
  • 2,389
  • 2
  • 22
  • 26
1

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];
Suresh Kumar
  • 455
  • 2
  • 5
  • 13
1

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.

1

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

SurpriseDog
  • 462
  • 8
  • 18
-5

Do not let any space in front of your brackets.

Example:

n = input ()
         ^

Tip: You should add comments over and/or under your code. Not behind your code.


Have a nice day.

  • 1
    Welcome to SO! Your reply looks like a comment rather than an answer. Once you have sufficient [reputation](http://stackoverflow.com/help/whats-reputation) you will be able to [comment](http://stackoverflow.com/help/privileges/comment) on any post. Also check this [what can I do instead](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). If you intended to Answer, read this [how-to-answer](http://stackoverflow.com/help/how-to-answer) to follow the SO guidelines. – thewaywewere May 07 '17 at 11:26