[python] Python: Find in list

I have come across this:

item = someSortOfSelection()
if item in myList:
    doMySpecialFunction(item)

but sometimes it does not work with all my items, as if they weren't recognized in the list (when it's a list of string).

Is this the most 'pythonic' way of finding an item in a list: if x in l:?

This question is related to python find

The answer is


Check there are no additional/unwanted whites space in the items of the list of strings. That's a reason that can be interfering explaining the items cannot be found.


While the answer from Niklas B. is pretty comprehensive, when we want to find an item in a list it is sometimes useful to get its index:

next((i for i, x in enumerate(lst) if [condition on x]), [default value])

Finding the first occurrence

There's a recipe for that in itertools:

def first_true(iterable, default=False, pred=None):
    """Returns the first true value in the iterable.

    If no true value is found, returns *default*

    If *pred* is not None, returns the first item
    for which pred(item) is true.

    """
    # first_true([a,b,c], x) --> a or b or c or x
    # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
    return next(filter(pred, iterable), default)

For example, the following code finds the first odd number in a list:

>>> first_true([2,3,4,5], None, lambda x: x%2==1)
3  

If you want to find one element or None use default in next, it won't raise StopIteration if the item was not found in the list:

first_or_default = next((x for x in lst if ...), None)

Definition and Usage

the count() method returns the number of elements with the specified value.

Syntax

list.count(value)

example:

fruits = ['apple', 'banana', 'cherry']

x = fruits.count("cherry")

Question's example:

item = someSortOfSelection()

if myList.count(item) >= 1 :

    doMySpecialFunction(item)

 lstr=[1, 2, 3]
 lstr=map(str,lstr)
 r=re.compile('^(3){1}')
 results=list(filter(r.match,lstr))
 print(results)

If you are going to check if value exist in the collectible once then using 'in' operator is fine. However, if you are going to check for more than once then I recommend using bisect module. Keep in mind that using bisect module data must be sorted. So you sort data once and then you can use bisect. Using bisect module on my machine is about 12 times faster than using 'in' operator.

Here is an example of code using Python 3.8 and above syntax:

import bisect
from timeit import timeit

def bisect_search(container, value):
    return (
      (index := bisect.bisect_left(container, value)) < len(container) 
      and container[index] == value
    )

data = list(range(1000))
# value to search
true_value = 666
false_value = 66666

# times to test
ttt = 1000

print(f"{bisect_search(data, true_value)=} {bisect_search(data, false_value)=}")

t1 = timeit(lambda: true_value in data, number=ttt)
t2 = timeit(lambda: bisect_search(data, true_value), number=ttt)

print("Performance:", f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")

Output:

bisect_search(data, true_value)=True bisect_search(data, false_value)=False
Performance: t1=0.0220, t2=0.0019, diffs t1/t2=11.71

You may want to use one of two possible searches while working with list of strings:

  1. if list element is equal to an item ('example' is in ['one','example','two']):

    if item in your_list: some_function_on_true()

    'ex' in ['one','ex','two'] => True

    'ex_1' in ['one','ex','two'] => False

  2. if list element is like an item ('ex' is in ['one,'example','two'] or 'example_1' is in ['one','example','two']):

    matches = [el for el in your_list if item in el]

    or

    matches = [el for el in your_list if el in item]

    then just check len(matches) or read them if needed.


Instead of using list.index(x) which returns the index of x if it is found in list or returns a #ValueError message if x is not found, you could use list.count(x) which returns the number of occurrences of x in list (validation that x is indeed in the list) or it returns 0 otherwise (in the absence of x). The cool thing about count() is that it doesn't break your code or require you to throw an exception for when x is not found


Another alternative: you can check if an item is in a list with if item in list:, but this is order O(n). If you are dealing with big lists of items and all you need to know is whether something is a member of your list, you can convert the list to a set first and take advantage of constant time set lookup:

my_set = set(my_list)
if item in my_set:  # much faster on average than using a list
    # do something

Not going to be the correct solution in every case, but for some cases this might give you better performance.

Note that creating the set with set(my_list) is also O(n), so if you only need to do this once then it isn't any faster to do it this way. If you need to repeatedly check membership though, then this will be O(1) for every lookup after that initial set creation.