Difference between: IF IN and IF == python - python

I wanted to know which condition is better to use for the following code:
Here are my two lists:
Matrix = ['kys_q1a1','kys_q1a2','kys_q1a3','kys_q1a4','kys_q1a5','kys_q1a6']
fixedlist = ['kys_q1a2', 'kys_q1a5']
Option 1:
for i, topmember in enumerate(Matrix):
for fixedcol in fixedlist:
if topmember in fixedcol:
print i
OR
Option 2:
for i, topmember in enumerate(Matrix):
for fixedcol in fixedlist:
if topmember == fixedcol:
print i
I understand that the comparison opertor is matching strings but isn't 'in' doing the same?
Thanks

topmember in fixedcol
tests if the string topmember is contained within fixedcol.
topmember == fixedcol
tests if the string topmember is equal to fixedcol.
So, 'a' in 'ab' would evaluate True. But 'a' == 'ab' would evaluate False.
I wanted to know which condition is better to use.
Since the two variants perform different operations, we cannot answer that. You need to choose the option that does the operation that you require.
Your code could be simplified quite a bit. The second option could be reduced to:
for i, topmember in enumerate(Matrix):
if topmember in fixedlist:
print i
You could also use a list comprehension to find the matching indices:
[i for i, x in enumerate(Matrix) if x in fixedlist]
If you just have to print the indices rather than store them in a list you can write it like this:
print '\n'.join([str(i) for i, x in enumerate(Matrix) if x in fixedlist])
It's a matter of taste whether you prefer the dense list comprehension one-liner, or the rather more verbose version above.

Hi in opeartor is used for membership testing and == operator is used for equality testing .
Generally we used in for membership testing in sequence object. And is able to test in dictionary, set, tuple, list, string etc. But it behaves differently based on the object types.
Dictionary:
It check for the key exists.
>>> d = {'key' : 'value'}
>>> 'key' in d
True
>>> 'k' in d
False
>>>
Set:
Under the hood it checks for key is exist, set implementation is same as dictionary with some dummy value.
>>> s = set(range(10))
>>> 1 in s
True
>>>
List and Tuple:
For the list and tuple types, x in y is true if and only if there exists an index i such that x == y[i] is true.
>>> l = range(10)
>>> 3 in l
True
>>>
String:
checking whether the substring is present inside the string eg. x in y is true if and only if x is a substring of y. An equivalent test is y.find(x) != -1
Use defined data type:
user-defined classes which define the __contains__() method, x in y is true if and only if y.__contains__(x) is true.
class Person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def __contains__(self, arg):
if arg in self.__dict__.keys():
return True
else:
return False
obj_p = Person('Jeff', 90)
print 'Jeff', 'Jeff' in obj_p
print 'age', 'age' in obj_p
print 'name', 'age' in obj_p
I Hope, you will clear some what is the usage of in.
Lets rewrite your snippet:
>>> Matrix = ['kys_q1a1','kys_q1a2','kys_q1a3','kys_q1a4','kys_q1a5','kys_q1a6']
>>> fixedlist = ['kys_q1a2', 'kys_q1a5']
>>> for i in fixedlist:
... print i, i in Matrix
...
kys_q1a2 True
kys_q1a5 True
>>>
And finally lets see some of the equality test: ==:
>>> 'a' == 'b'
False
>>> 'a' == 'a'
True
>>> 'a' == 'ab'
False
>>> '' in 'ab' # empty string is treated as a sub-string for any string
True
>>> '' == 'ab' # False as they are having different values
False
>>>
>>> 1 == 'ab'
False
>>> 1 == 1
True
>>>

Going with '==' is precise if you want to match exact string.

Related

Python: general iterator or pure function for testing any condition across list

I would like to have a function AllTrue that takes three arguments:
List: a list of values
Function: a function to apply to all values
Condition: something to test against the function's output
and return a boolean of whether or not all values in the list match the criteria.
I can get this to work for basic conditions as follows:
def AllTrue(List, Function = "Boolean", Condition = True):
flag = True
condition = Condition
if Function == "Boolean"
for element in List:
if element != condition:
flag = False
break
else:
Map = map(Function, List)
for m in Map:
if m != condition:
flag = False
break
return flag
Since python doesn't have function meant for explicitly returning if something is True, I just make the default "Boolean". One could clean this up by defining TrueQ to return True if an element is True and then just mapping TrueQ on the List.
The else handles queries like:
l = [[0,1], [2,3,4,5], [6,7], [8,9],[10]]
AllTrue(l, len, 2)
#False
testing if all elements in the list are of length 2. However, it can't handle more complex conditions like >/< or compound conditions like len > 2 and element[0] == 15
How can one do this?
Cleaned up version
def TrueQ(item):
return item == True
def AllTrue(List, Function = TrueQ, Condition = True):
flag = True
condition = Condition
Map = map(Function, List)
for m in Map:
if m != condition:
flag = False
break
return flag
and then just call AllTrue(List,TrueQ)
Python already has built-in the machinery you are trying to build. For example to check if all numbers in a list are even the code could be:
if all(x%2==0 for x in L):
...
if you want to check that all values are "truthy" the code is even simpler:
if all(L):
...
Note that in the first version the code is also "short-circuited", in other words the evaluation stops as soon as the result is known. In:
if all(price(x) > 100 for x in stocks):
...
the function price will be called until the first stock is found with a lower or equal price value. At that point the search will stop because the result is known to be False.
To check that all lengths are 2 in the list L the code is simply:
if all(len(x) == 2 for x in L):
...
i.e. more or less a literal translation of the request. No need to write a function for that.
If this kind of test is a "filter" that you want to pass as a parameter to another function then a lambda may turn out useful:
def search_DB(test):
for record in database:
if test(record):
result.append(record)
...
search_DB(lambda rec: all(len(x) == 2 for x in rec.strings))
I want a function that takes a list, a function, and a condition, and tells me if every element in the list matches the condition. i.e. foo(List, Len, >2)
In Python >2 is written lambda x : x>2.
There is (unfortunately) no metaprogramming facility in Python that would allow to write just >2 or things like ยท>2 except using a string literal evaluation with eval and you don't want to do that. Even the standard Python library tried going down that path (see namedtuple implementation in collections) but it's really ugly.
I'm not saying that writing >2 would be a good idea, but that it would be nice to have a way to do that in case it was a good idea. Unfortunately to have decent metaprogramming abilities you need a homoiconic language representing code as data and therefore you would be programming in Lisp or another meta-language, not Python (programming in Lisp would indeed be a good idea, but for reasons unknown to me that approach is still unpopular).
Given that, the function foo to be called like
foo(L, len, lambda x : x > 2)
is just
def foo(L, f=lambda x : x, condition=lambda x: x):
return all(condition(f(x)) for x in L)
but no Python programmer would write such a function, because the original call to foo is actually more code and less clear than inlining it with:
all(len(x) > 2 for x in L)
and requires you to also learn about this thing foo (that does what all and a generator expression would do, just slower, with more code and more obfuscated).
You are reinventing the wheel. Just use something like this:
>>> l = [[0,1], [2,3,4,5], [6,7], [8,9],[10]]
>>> def all_true(iterable, f, condition):
... return all(condition(f(e)) for e in iterable)
...
>>> def cond(x): return x == 2
...
>>> all_true(l, len, cond)
False
You can define a different function to check a different condition:
>>> def cond(x): return x >= 1
...
>>> all_true(l, len, b)
True
>>>
And really, having your own function that does this seems like overkill. For example, to deal with your "complex condition" you could simply do something like:
>>> l = [[0,2],[0,1,2],[0,1,3,4]]
>>> all(len(sub) > 2 and sub[0] == 5 for sub in l)
False
>>> all(len(sub) > 1 and sub[0] == 0 for sub in l)
True
>>>
I think the ideal solution in this case may be:
def AllTrue(List, Test = lambda x:x):
all(Test(x) for x in List)
This thereby allows complex queries like:
l = [[0, 1], [1, 2, 3], [2, 5]]
AllTrue(l, lambda x: len(x) > 2 and x[0] == 1)
To adhere to Juanpa's suggestion, here it is in python naming conventions and an extension of what I posted in the question now with the ability to handle simple conditions like x > value.
from operator import *
all_true(a_list, a_function, an_operator, a_value):
a_map = map(a_function, a_list)
return all( an_operator(m, a_value) for m in a_map)
l = [[0,2],[0,1,2],[0,1,3,4]]
all_true(l, len, gt, 2)
#True
Note: this works for single conditions, but not for complex conditions like
len > 2 and element[0] == 5

Differentiate False and 0

Let's say I have a list with different values, like this:
[1,2,3,'b', None, False, True, 7.0]
I want to iterate over it and check that every element is not in list of some forbidden values. For example, this list is [0,0.0].
When I check if False in [0,0.0] I get True. I understand that python casts False to 0 here - but how I can avoid it and make this check right - that False value is not in [0,0.0]?
To tell the difference between False and 0 you may use is to compare them. False is a singleton value and always refers to the same object. To compare all the items in a list to make sure they are not False, try:
all(x is not False for x in a_list)
BTW, Python doesn't cast anything here: Booleans are a subclass of integers, and False is literally equal to 0, no conversion required.
You would want to use is instead of == when comparing.
y = 0
print y == False # True
print y is False # False
x = False
print x == False # True
print x is False # True
Found a weird corner case on differentiating between 0 and False today. If the initial list contains the numpy version of False (numpy.bool_(False)), the is comparisons don't work, because numpy.bool_(False) is not False.
These arise all the time in comparisons that use numpy types. For example:
>>> type(numpy.array(50)<0)
<class 'numpy.bool_'>
The easiest way would be to compare using the numpy.bool_ type: (np.array(50)<0) is (np.False_). But doing that requires a numpy dependency. The solution I came up with was to do a string comparison (working as of numpy 1.18.1):
str(numpy.bool_(False)) == str(False)
So when dealing with a list, a la #kindall it would be:
all(str(x) != str(False) for x in a_list)
Note that this test also has a problem with the string 'False'. To avoid that, you could exclude against cases where the string representation was equivalent to itself (this also dodges a numpy string array). Here's some test outputs:
>>> foo = False
>>> str(foo) != foo and str(foo) == str(False)
True
>>> foo = numpy.bool_(False)
>>> str(foo) != foo and str(foo) == str(False)
True
>>> foo = 0
>>> str(foo) != foo and str(foo) == str(False)
False
>>> foo = 'False'
>>> str(foo) != foo and str(foo) == str(False)
False
>>> foo = numpy.array('False')
>>> str(foo) != foo and str(foo) == str(False)
array(False)
I am not really an expert programmer, so there may be some limitations I've still missed, or a big reason not to do this, but it allowed me to differentiate 0 and False without needing to resort to a numpy dependency.

How can I return false if more than one number while ignoring "0"'s?

This is a function in a greater a program that solves a sudoku puzzle. At this point, I would like the function to return false if there is more then 1 occurrence of a number unless the number is zero. What do am I missing to achieve this?
L is a list of numbers
l =[1,0,0,2,3,0,0,8,0]
def alldifferent1D(l):
for i in range(len(l)):
if l.count(l[i])>1 and l[i] != 0: #does this do it?
return False
return True
Assuming the list is length 9, you can ignore the inefficiency of using count here (Using a helper datastructure - Counter etc probably takes longer than running .count() a few times). You can write the expression to say they are all different more naturally as:
def alldifferent1D(L):
return all(L.count(x) <= 1 for x in L if x != 0)
This also saves calling count() for all the 0's
>>> from collections import counter
>>> def all_different(xs):
... return len(set(Counter(filter(None, xs)).values()) - set([1])) == 0
Tests:
>>> all_different([])
True
>>> all_different([0,0,0])
True
>>> all_different([0,0,1,2,3])
True
>>> all_different([1])
True
>>> all_different([1,2])
True
>>> all_different([0,2,0,1,2,3])
False
>>> all_different([2,2])
False
>>> all_different([1,2,3,2,2,3])
False
So we can break this down into two problems:
Getting rid of the zeros, since we don't care about them.
Checking if there are any duplicate numbers.
Striping the zeros is easy enough:
filter(lambda a: a != 0, x)
And we can check for differences in a set (which has only one of each element) and a list
if len(x) == len(set(x)):
return True
return False
Making these into functions we have:
def remove_zeros(x):
return filter(lambda a: a != 0, x)
def duplicates(x):
if len(x) == len(set(x)):
return True
return False
def alldifferent1D(x):
return duplicates(remove_zeros(x))
One way to avoid searching for every entry in every position is to:
flags = (len(l)+1)*[False];
for cell in l:
if cell>0:
if flags[cell]:
return False
flags[cell] = True
return True
The flags list has a True at index k if the value k has been seen before in the list.
I'm sure you could speed this up with list comprehension and an all() or any() test, but this worked well enough for me.
PS: The first intro didn't survive my edit, but this is from a Sudoku solver I wrote years ago. (Python 2.4 or 2.5 iirc)

does adding element to a set return true if it is successful in python?

To my understanding, adding elements to a set does not return anything.
eg:
>>> s=set([1,2,3])
>>> s.add(1)
>>> b = s.add(1)
>>> b
>>> b = s.add(5)
>>> b
>>> print b
None
>>> b = s.add(5)
>>> print b
None
but I am confused how this function to remove duplicates of a list while preserving order works:
def f7(seq):
seen = set()
seen_add = seen.add
return [ x for x in seq if x not in seen and not seen_add(x)]
not seen_add(x) return true always irrespective of if I add duplicates or not.
The only real check is if x not in seen, since if that fails, it will not perform not see_add(x).
Is my understanding here or am I missing something?
however, here, not seen_add(1) return true if I add duplicate or a unique element.
This is puzzling, so is the not here just do an empty check? but seen_add() is not returning a set to do an empty check. and why seen_add(2) does not return anything but not seen_add(1) returns the boolean True
>>> seen=set()
>>> seen_add=seen.add
>>> seen_add(1)
>>> seen
set([1])
>>> seen.add(2)
>>> seen
set([1, 2])
>>> not seen_add(1)
True
>>> not seen_add(4)
True
As you have discovered, seen_add(x) always returns None.
Now, not None is True:
>>> not None
True
This is explained in the documentation:
5.1. Truth Value Testing
Any object can be tested for truth value, for use in an if or while condition or as operand of the Boolean operations below. The following values are considered false:
None
False
...
Since not seen_add(x) is always True, it has no effect on the result of the if. It is only used for the side effect of adding x to seen.
Put another way, the following:
seen_add = seen.add
return [ x for x in seq if x not in seen and not seen_add(x)]
is a shorter (and likely more performant) way to write:
result = []
for x in seq:
if x not in seen:
result.append(x)
seen.add(x)
return result
As said by the others, not seen_add(x) always evaluates to True, so it is used only as a hack to add the addition statement into the list comprehension. Since the logic value of x and True is equal to x, this does not change the behavior of the if.
Another thing that this does, due to the short-circuit behavior of and, is that the right-hand argument to and is only executed if the left-hand argument is True. So the call to seen.add() is only done when the element is not yet in the set.
The equivalent python code would be:
def f7(seq):
seen = set()
result = []
for x in seq:
if x not in seen:
result.append(x)
seen.add(x)
return result
The solution with the list comprehension might be faster, but it is too cryptic to my taste.
This is because not None is True.
maybe this can help you
def add_ok(set, value):
return len(set) != (set.add(value), len(set))[1]
print(add_ok(a, 1))
print(add_ok(a, 1))

How do I check existence of a string in a list of strings, including substrings?

I have written a function to check for the existence of a value in a list and return True if it exists. It works well for exact matches, but I need for it to return True if the value exists anywhere in the list entry (e.g. value <= listEntry, I think.) Here is the code I am using for the function:
def isValInLst(val,lst):
"""check to see if val is in lst. If it doesn't NOT exist (i.e. != 0),
return True. Otherwise return false."""
if lst.count(val) != 0:
return True
else:
print 'val is '+str(val)
return False
Without looping through the entire character string and/or using RegEx's (unless those are the most efficient), how should I go about this in a pythonic manner?
This is very similar to another SO question, but I need to check for the existence of the ENTIRE val string anywhere in the list. It would also be great to return the index / indices of matches, but I'm sure that's covered elsewhere on Stackoverflow.
If I understood your question then I guess you need any:
return any(val in x for x in lst)
Demo:
>>> lst = ['aaa','dfbbsd','sdfdee']
>>> val = 'bb'
>>> any(val in x for x in lst)
True
>>> val = "foo"
>>> any(val in x for x in lst)
False
>>> val = "fde"
>>> any(val in x for x in lst)
True
Mostly covered, but if you want to get the index of the matches I would suggest something like this:
indices = [index for index, content in enumerate(input) if substring in content]
if you want to add in the true/false you can still directly use the result from this list comprehension since it will return an empty list if your input doesn't contain the substring which will evaluate to False.
In the terms of your first function:
def isValInLst(val, lst):
return bool([index for index, content in enumerate(lst) if val in content])
where the bool() just converts the answer into a boolean value, but without the bool this will return a list of all places where the substring appears in the list.
There are multiple possibilities to do that. For example:
def valInList1 (val, lst):
# check `in` for each element in the list
return any(val in x for x in lst)
def valInList2 (val, lst):
# join the list to a single string using some character
# that definitely does not occur in val
return val in ';;;'.join(lst)

Categories