I am checking whether a list in python contains only numeric data. For simple ints and floats I can use the following code:
if all(isinstance(x, (int, float)) for x in lstA):
If there any easy way to check whether another list is embedded in the first list also containing numeric data?
You can do a recursive check for all lists within the list, like so
def is_all_numeric(lst):
for elem in lst:
if isinstance(elem, list):
if not is_all_numeric(elem):
return False
elif not isinstance(elem, (int, float)):
return False
return True
print(is_all_numeric([1,2,3]))
>>> True
print(is_all_numeric([1,2,'a']))
>>> False
print(is_all_numeric([1,2,[1,2,3]]))
>>> True
print(is_all_numeric([1,2,[1,2,'a']]))
>>> False
I don't know if there is another way to do this, but you could just do a for loop for each item, and if any of those items is not a number, just set on bool to false:
numbers = [1,2,3,4,5,6,7,8]
allListIsNumber = True
for i in numbers:
if i.isnumeric() == False:
allListIsNumber = False
You can either use isnumeric() or isinstance()
Related
I'm trying to solve this problem in Python: "Write a function to return True when its argument is an array that has the same nesting structures and same corresponding length of nested arrays as the first array."
So I want to compare 2 lists, check if their elements are lists, and if so then check if the elements of these lists are lists, and so on, until I find the point where "original" doesn't match "other.
So far I've got:
def same_structure_as(original,other):
print(type(original))
print(type(other))
# if either, but not both of original and other are a list, return False
if (type(original) is list) != (type(other) is list):
print("not match")
return False
print()
if (type(original) is list):
for i in range(len(original)):
if (type(original[i]) is list):
same_structure_as(original[i],other[i])
return True
print(same_structure_as([ 1, [ 1, 1 ] ], [ 2, 5 ] ))
However, the problem is that once I get to the "return False", it only returns False for this iteration. So the iterations above this will still return True, giving the below output when run:
<class 'list'>
<class 'list'>
<class 'list'>
<class 'int'>
not match
True
whereas I want the entire program to exit and return False immediately after "not match" gets printed...
Adding a check on the line of recursive calling function may help you to resolve your problem. By doing that when ever there is a mismatch it will return back False through all the steps of recursion.
def same_structure_as(original,other):
print(type(original))
print(type(other))
# if either, but not both of original and other are a list, return False
if (type(original) is list) != (type(other) is list):
print("not match")
return False
print()
if (type(original) is list):
for i in range(len(original)):
if (type(original[i]) is list):
if(same_structure_as(original[i],other[i])==False):
return False
return True
print(same_structure_as([ 1, [ 1, 1 ] ], [ 2, 5 ] ))
The issue is that you are calling same_structure_as for the elements of the list, but you are not using the return value.
The recursive part is called for each element of the list. You need to combine them together and return the combined result. The idea is that for two lists to return True, you need the following condition:
same_as(a[0], b[0]) && same_as(a[1], b[1]) && ... && same_as(a[n], b[n])
The logic of the function should be something like this:
def same_as(a ,b):
# If the two elements have different types, then they're definitely not matching
if type(a) != type(b): return False
# Now both elements are the same type.
# If they are not lists, it means there is no nested elements. So they have the same structure
If type(a) is not list: return True
# At this point, both elements are lists. Check first if their sizes are the same
if len(a) != len(b): return False
# Now the elements are lists of the same size. Compare each sub-element inside a loop
# For the two lists to be the same structure, *ALL* their elements must be the same structure.
# We will use the AND operator
equal = False
For i = 0:len(a):
equal = equal && same_as(a[i], b[i])
# Now the boolean 'equal' will be True ONLY if ALL the sub-elements returned True
return equal
I'm a beginner in Python programming and I'm having some trouble with some list stuff.
So I want to write a function that returns a boolean value. The function will inform the user whether there is a duplicate consecutive pair of elements in the list he or she entered. By the way, I want to do this using only len(), range(), loops, if-statements, variables and arithmetic (no built in functions).
For example:
contains_consecutive_duplicates([1,3,3]) should return True
contains_consecutive_duplicates([3,2,3]) should return False
My code:
def contains_consecutive_duplicates(xs):
for i in xs:
if xs[i] == xs[i-1] or xs[i] == xs[i+1]:
return True
else:
return False
My logic to this was as follows: Each time the for loop would run, i would refer to some element in the list. If that element was such that the element before it or after it was equal to it, then the for loop would return true. If not, keep searching. If there are none, it would return false.
Now, I actually understand where the error is (I think). The problem is that I don't know how to solve it. I think the for loop is running into a problem at the beginning (when i is reffering to the 0th element). There is no element before the 0th element, hence the error:
"index out of range"
P.S: Is that how you return a boolean value?
Is there a better way to do this?
I would appreciate any help given! Thanks in advance!
#roeland pointed out the problem with assuming iterating the list directly would get you indices (if you want index and value, use enumerate). But in this case you don't actually need the index.
For the simple case (where it's known to be a container you can slice), you can just iterate with zip over offset slices:
def contains_consecutive_duplicates(xs):
return any(x == y for x, y in zip(xs, xs[1:]))
More general solutions can be made with itertools.groupby to handle the case where you can't slice, but this is simple and involves no imports.
Use of any in this case is just a short hand to slurp the generator expression and return True if any values are truthy. The long equivalent form is:
def contains_consecutive_duplicates(xs):
for x1, x2 in zip(xs, xs[1:]):
if x1 == x2:
return True
return False
Since your teacher apparently thinks built-ins are bad, but len and range aren't built-ins (they are), you can do this the dumb way:
def contains_consecutive_duplicates(xs):
for i in range(len(xs) - 1):
if xs[i] == xs[i+1]:
return True
return False
Which does the same work as ziping, just less efficiently (generating index integers and explicitly indexing is surprisingly expensive in Python relative to native iteration).
This should do:
>>> def contains_consecutive_duplicates(xs):
... for i, v in enumerate(xs[:-1]):
... if v == xs[i+1]:
... return True
... else:
... pass
... return False
>>> l1 = [1,3,3]
>>> l2 = [1,3,2]
>>> l3 = []
>>> l4 = [2]
>>> contains_consecutive_duplicates(l1)
True
>>> contains_consecutive_duplicates(l2)
False
>>> contains_consecutive_duplicates(l3)
False
>>> contains_consecutive_duplicates(l4)
False
>>>
By using only range, for and if statements, this can be done with:
def contains_consequtive_duplicates(xs):
for i in range(len(xs)-1):
if xs[i] == xs[i+1]: return True
return False
You access lists with their index and not by their value (which you are by using for i in list). Additionally, if you perform the check xs[i] == xs[i-1] this will not yield the result you want since x[-1] will check the end of the list so [3, 2, 3] will return True.
As a small demonstration:
if contains_consequtive_duplicates([1,3,3]): print "consecutive"
# Prints Consequtive
if contains_consequtive_duplicates([3, 2, 3]): print "consecutive"
# Prints nothing
Try this:
def contains_consecutive_duplicates(xs):
for i in xs:
if xs.indexOf(i)==len(xs):
break
if xs[i] == xs[i-1] or xs[i] == xs[i+1]:
return True
else:
return False
What you are doing is trying to do is evaluate xs[i+1], but that does not exist.
This should do the trick:
def contains_consecutive_duplicates(xs):
for i in range(1, len(xs) - 1):
if xs[i] == xs[i-1] or xs[i] == xs[i+1]:
return True
return False
It iterates through all values bar the first and last (created by the range function), returning (which ends the loop) if it finds a duplicate.
If it reaches the end and hasn't found a duplicate one must not exist, so it returns False.
Suppose,
var = ('x', 3)
How to check if a variable is a tuple with only two elements, first being a type str and the other a type int in python?
Can we do this using only one check?
I want to avoid this -
if isinstance(var, tuple):
if isinstance (var[0], str) and (var[1], int):
return True
return False
Here's a simple one-liner:
isinstance(v, tuple) and list(map(type, v)) == [str, int]
Try it out:
>>> def check(v):
return isinstance(v, tuple) and list(map(type, v)) == [str, int]
...
>>> check(0)
False
>>> check(('x', 3, 4))
False
>>> check((3, 4))
False
>>> check(['x', 3])
False
>>> check(('x', 3))
True
Well considering tuples are variable in length you're not going to find a method that checks this instance of all it's types. What's wrong with the method you have? It's clear what it does and it fits your usage. You're not going to find a pretty one liner AFAIK.
And you do have a one liner... Technically:
def isMyTuple(my_tuple):
return isinstance(my_tuple,(tuple, list)) and isinstance(my_tuple[0],str) and isinstance(my_tuple[1],int)
var = ('x', 3)
print isMyTuple(var)
If you're going to do this check many times, calling the method is DRY!
Not exactly what you ask for, but you might find it useful.
from itertools import izip_longest
def typemap(iterable, types, *indexes):
# izip_longest helps with the length check, because we will get a TypeError if len(iterable) > len(types)
try:
_iterable = ((elem for ind, elem in enumerate(iterable)
if ind in indexes) if indexes else iterable)
return all(isinstance(elem, _type)
for elem, _type in izip_longest(_iterable, types))
except TypeError:
return False
typemap((1, 2, "ch", {}, []), (int, int, str, dict, list)) # -> True
typemap((1, 2, "ch", {}, []), (int, int, str, dict)) # -> False
typemap((1, 2, "ch", {}, []), (int, int, str, list), 0, 1, 2, 4) # -> True
You can chain all your ifs on one line:
result = isinstance(var, tuple) and isinstance(var[0], str) and isinstance(var[1], int)
result will be True is all conditions match, else it'll be False
You can pass a tuple of arguments to isinstance to test for a list or a tuple:
def test(t):
return isinstance(t, (tuple, list))and len(t) == 2 and\
isinstance(t[0], str) and isinstance(t[1], int)
If you only want to accept either lists or tuples with two elements you need the check for the length, if it did not have to be 2 you would still need to make sure it had at least two elements to avoid an indexError
You could go down the route of begging forgiveness:
def isMyTuple( var):
try:
return isinstance(var, tuple) and \
isinstance (var[0], str) and \
isinstance(var[1], int)
except:
return False
I'm not entirely certain you need the try ... except in this case. Python uses short-circult logic. If it's not a tuple the second and third tests don't get executed and so you don't crash out trying to index a non-indexable var. But just possibly, someone derived a class from Tuple and modified it so its indexes aren't integers, or some other wierdness.
BTW should you should also check len(var)==2 ?
You can write your own function that checks if a variable matches a specification:
def istype(var, spec):
if type(var) != type(spec):
return False
if isinstance(spec, tuple):
if len(var) != len(spec):
return False
return all([istype(var[i], spec[i]) for i in range(len(var))])
return True
You have to add more checks for other types, but for your example this will suffice.
>>> istype((1,'x'), (2,'y'))
True
I want to make condition than number has to be integer. And x == int(x) doesn't help in cases when x == 1.0...
Thank you.
isinstance(x, (int, long))
isinstance tests whether the first argument is an instance of the type or types specified by the second argument. We specify (int, long) to handle cases where Python automatically switches to longs to represent very large numbers, but you can use int if you're sure you want to exclude longs. See the docs for more details.
As for why 1.0 == 1, it's because 1.0 and 1 represent the same number. Python doesn't require that two objects have the same type for them to be considered equal.
Not big on python, but I used this to check:
i = 123
f = 123.0
if type(i) == type(f) and i == f:
print("They're equal by value and type!")
elif type(i) == type(f):
print("They're equal by type and not value.")
elif i == f:
print("They're equal by value and not type.")
else:
print("They aren't equal by value or type.")
Returns:
They're equal by value and not type.
Just check if it's an integer.
>>> def int_check(valuechk, valuecmp):
if valuechk == valuecmp and type(valuechk) == int:
return True
else:
return False
>>> int_check(1, 1)
True
>>> int_check(1.0, 1)
False
Python converts the integer value into its real equivalent, then checks the two values, and thus the answer is true when checking value equivalence, but if one is checking type equivalence then the answer is false.
Design a logical expression equivalent to the following statement:
x is a list of three or five elements, the second element of which is
the string 'Hip' and the first of which is not a number or Boolean.
What I have:
x = ['Head', 'Hip', 10]
print x[1] is 'Hip'
My question: How do you check for whether or not it is a Boolean or a number?
To answer the specific question:
isinstance(x[0], (int, float))
This checks if x[0] is an instance of any of the types in the tuple (int, float).
You can add bool in there, too, but it's not necessary, because bool is itself a subclass of int.
Doc reference:
isinstance()
built-in numeric types
To comment on your current code, you shouldn't rely on interning of short strings. You are supposed to compare strings with the == operator:
x[1] == 'Hip'
Easiest i would say:
type(x) == type(True)
In python3 this would be: type(x)==bool see example.
Python 2
import types
x = False
print(type(x) == types.BooleanType) # True
Python 3
# No need to import types module
x = False
print(type(x) == bool) # True
You should compare the type of x to the bool class:
type(x) == bool
or:
type(x) == type(True)
Here is more on the type method
From Data model docs:
Booleans (bool)
These represent the truth values False and True. The two objects representing the values False and True are the only Boolean objects. The Boolean type is a subtype of the integer type, and Boolean values behave like the values 0 and 1, respectively, in almost all contexts, the exception being that when converted to a string, the strings "False" or "True" are returned, respectively.
I follow the recent answer who tell to use type and it seems to be the incorrect way according to pylint validation:
I got the message:
C0123: Using type() instead of isinstance() for a typecheck.
(unidiomatic-typecheck)
Even if it's an old answer, the correct one is the accepted answer of #Lev Levitsky:
isinstance(x[0], (int, float))
Python 3:
Use assert to check is some statement is True or False. If False, it will raise an AssertionError.
assert(isinstance(x[0], (int, float)))
You can then catch the error like that:
except AssertionError as error:
print(error)
# do stuff...
I like to keep it simple to read..
This will accept bool, string, number and read it to a bool
def var2bool(v):
if type(v) == type(True):
res = v
elif type(v) == type(0):
if v == 0:
res = False
else:
res = True
elif v.lower() in ("yes", "true", "t", "1"):
res = True
else:
res = False
return res