I did some google searching on how to check if a string has any elements of a list in it and I found this bit of code that works:
if any(i in string for i in list):
I know this works, but I don't really know why. Could you share some insight?
As the docs for any say:
Return True if any element of the iterable is true. If the iterable is empty, return False. Equivalent to:
def any(iterable):
for element in iterable:
if element:
return True
return False
So, this is equivalent to:
for element in (i in string for i in list):
if element:
return True
return False
… which is itself effectively equivalent to:
for i in list:
element = i in string
if element:
return True
return False
If you don't understand the last part, first read the tutorial section on list comprehensions, then skip ahead to iterators, generators, and generator expressions.
If you want to really break it down, you can do this:
elements = []
for i in list:
elements.append(i in string)
for element in elements:
if element:
return True
return False
That still isn't exactly the same, because a generator expression builds a generator, not a list, but it should be enough to get you going until you read the tutorial sections.
But meanwhile, the point of having any and comprehensions and so on is that you can almost read them as plain English:
if any(i in string for i in list): # Python
if any of the i's is in the string, for each i in the list: # pseudo-English
i in string for i in list
This produces an iterable of booleans indicating whether each item in list is in string. Then you check whether any item in this iterable of bools is true.
In effect, you're checking whether any of the items in the list are substrings of string.
What's going on here with:
if any(i in string for i in list):
is best explained by illustrating:
>>> xs = ["Goodbye", "Foo", "Balloon"]
>>> s = "Goodbye World"
>>> [i in s for i in xs]
[True, False, False]
>>> any([i in s for i in xs])
True
If you read the any documentaiton you'll note:
any(iterable) Return True if any element of the iterable is true.
If the iterable is empty, return False. Equivalent to:
The list comprehension should be more obvious as it constructs a list of i in s for each element of xs.
Basically (in English) you are returning any match where each sub-string exists in the search string (haystack).
It's important to note as well that any() will short circuit and end on the first True(ish) value it finds. any() can be implement in pure Python like this:
def any(iterable):
for x in iterable:
if x:
return True
return False
Related
Is there a built-in python equivalent of std::find_if to find the first element of a list for which a given condition is true? In other words, something like the index() function of a list, but with an arbitrary unary predicate rather than just a test for equality.
I don't want to use list comprehension, because the specific predicate I have in mind is somewhat expensive to compute.
Using a tip from an answer to a related question, and borrowing from the answer taras posted, I came up with this:
>>> lst=[1,2,10,3,5,3,4]
>>> next(n for n in lst if n%5==0)
10
A slight modification will give you the index rather than the value:
>>> next(idx for idx,n in enumerate(lst) if n%5==0)
2
Now, if there was no match this will raise an exception StopIteration. You might want use a function that handles the exception and returns None if there was no match:
def first_match(iterable, predicate):
try:
return next(idx for idx,n in enumerate(iterable) if predicate(n))
except StopIteration:
return None
lst=[1,2,10,3,5,3,4]
print(first_match(lst, lambda x: x%5 == 0))
Note that this uses a generator expression, not a list comprehension. A list comprehension would apply the condition to every member of the list and produce a list of all matches. This applies it to each member until it finds a match and then stops, which is the minimum work to solve the problem.
Say, you have some predicate function pred and a list lst.
You can use itertools.dropwhile to get the first element in lst,
for which pred returns True with
itertools.dropwhile(lambda x: not pred(x), lst).next()
It skips all elements for which pred(x) is False and .next()
yields you the value for which pred(x) is True.
Edit:
A sample use to find the first element in lst divisible by 5
>>> import itertools
>>> lst = [1,2,10,3,5,3,4]
>>> pred = lambda x: x % 5 == 0
>>> itertools.dropwhile(lambda x: not pred(x), lst).next()
10
In Python, asking if a substring exists in a string is pretty straightforward:
>>> their_string = 'abracadabra'
>>> our_string = 'cad'
>>> our_string in their_string
True
However, checking if these same characters are "in" a list fails:
>>> ours, theirs = map(list, [our_string, their_string])
>>> ours in theirs
False
>>> ours, theirs = map(tuple, [our_string, their_string])
>>> ours in theirs
False
I wasn't able to find any obvious reason why checking for elements "in" an ordered (even immutable) iterable would behave differently than a different type of ordered, immutable iterable.
For container types such as lists and tuples, x in container checks if x is an item in the container. Thus with ours in theirs, Python checks if ours is an item in theirs and finds that it is False.
Remember that a list could contain a list. (e.g [['a','b','c'], ...])
>>> ours = ['a','b','c']
>>> theirs = [['a','b','c'], 1, 2]
>>> ours in theirs
True
Are you looking to see if 'cad' is in any of the strings in a list of strings? That would like something like:
stringsToSearch = ['blah', 'foo', 'bar', 'abracadabra']
if any('cad' in s for s in stringsToSearch):
# 'cad' was in at least one string in the list
else:
# none of the strings in the list contain 'cad'
From the Python documentation, https://docs.python.org/2/library/stdtypes.html for sequences:
x in s True if an item of s is equal to x, else False (1)
x not in s False if an item of s is equal to x, else True (1)
(1) When s is a string or Unicode string object the in and not in operations act like a substring test.
For user defined classes, the __contains__ method implements this in test. list and tuple implement the basic notion. string has the added notion of 'substring'. string is a special case among the basic sequences.
Is there any ways we can detect if an object is list in python using type(obj) --> list.
But how can we detect if the object is list of list of the form as:
[['a','b']['a','b'][][]]
Use isinstance() to check for a specific type:
>>> isinstance([], list)
True
Use all() to test if all elements are of a certain type:
all(isinstance(elem, list) for elem in list_of_lists)
all() short-circuits; if any of the tests returns False, the loop is terminated and False is returned. Only if all but one element returns True does all() need to examine every element of the iterable.
If you want to make sure that every item in your list is a list, you could do something like this:
if all(isinstance(i, list) for i in lst):
# All of the items are lists
isinstance(i, list) is the better way of writing type(i) == type(list) or type(i) == list).
all() returns True if all of the items in the sequence are True. It'll return False if any aren't True.
Given a list xs and a value item, how can I check whether xs contains item (i.e., if any of the elements of xs is equal to item)? Is there something like xs.contains(item)?
For performance considerations, see Fastest way to check if a value exists in a list.
Use:
if my_item in some_list:
...
Also, inverse operation:
if my_item not in some_list:
...
It works fine for lists, tuples, sets and dicts (check keys).
Note that this is an O(n) operation in lists and tuples, but an O(1) operation in sets and dicts.
In addition to what other have said, you may also be interested to know that what in does is to call the list.__contains__ method, that you can define on any class you write and can get extremely handy to use python at his full extent.
A dumb use may be:
>>> class ContainsEverything:
def __init__(self):
return None
def __contains__(self, *elem, **k):
return True
>>> a = ContainsEverything()
>>> 3 in a
True
>>> a in a
True
>>> False in a
True
>>> False not in a
False
>>>
I came up with this one liner recently for getting True if a list contains any number of occurrences of an item, or False if it contains no occurrences or nothing at all. Using next(...) gives this a default return value (False) and means it should run significantly faster than running the whole list comprehension.
list_does_contain = next((True for item in list_to_test if item == test_item), False)
The list method index will return -1 if the item is not present, and will return the index of the item in the list if it is present. Alternatively in an if statement you can do the following:
if myItem in list:
#do things
You can also check if an element is not in a list with the following if statement:
if myItem not in list:
#do things
There is also the list method:
[2, 51, 6, 8, 3].__contains__(8)
# Out[33]: True
[2, 51, 6, 3].__contains__(8)
# Out[33]: False
There is one another method that uses index. But I am not sure if this has any fault or not.
list = [5,4,3,1]
try:
list.index(2)
#code for when item is expected to be in the list
print("present")
except:
#code for when item is not expected to be in the list
print("not present")
Output:
not present
Basically my question is say you have an list containing 'None' how would you try retrieving the sum of the list. Below is an example I tried which doesn't work and I get the error: TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'. Thanks
def sumImport(self):
my_list = [[1,2,3,None],[1,2,3],[1,1],[1,1,2,2]]
k = sum(chain.from_iterable(my_list))
return k
You can use filter function
>>> sum(filter(None, [1,2,3,None]))
6
Updated from comments
Typically filter usage is filter(func, iterable), but passing None as first argument is a special case, described in Python docs. Quoting:
If function is None, the identity function is assumed, that is, all elements of iterable that are false are removed.
Remove None (and zero) elements before summing by using filter:
>>> k = sum(filter(None, chain.from_iterable(my_list)))
>>> k
20
To see why this works, see the documentation for filter:
filter(function, iterable)
Construct a list from those elements of iterable for which function returns true. iterable may be either a sequence, a container which supports iteration, or an iterator. If iterable is a string or a tuple, the result also has that type; otherwise it is always a list. If function is None, the identity function is assumed, that is, all elements of iterable that are false are removed.
Note that filter(function, iterable) is equivalent to [item for item in iterable if function(item)] if function is not None and [item for item in iterable if item] if function is None.
Another suggestion:
from itertools import chain
k = sum(x for x in chain.from_iterable(my_list) if x)
Assuming you want to treat None as zero, a simple way is
sum(x if x is not None else 0 for x in chain.from_iterable(my_list))
Explicitly, this is equivalent to filter:
k = sum([x for x in chain.from_iterable(my_list) if x])
That saves me from remembering another function. :P
You always have the option of just writing the loop you want:
k = 0
for sublist in my_list:
for val in sublist:
if val is not None:
k += val
But it certainly doesn’t hurt to know about filter either.
Just using sum and map:
sum(map(lambda x: x or 0, [1,2,3,None]))
# 6