Is there a way to check two conditions? For example,
a=np.array([1,2,3,4,5,6,7,8])
if any(a != 0 and a!=1)==True:
do something
EDIT: Answer provided. No need for any more input. Cheers
You need to use a generator object or iterable containing Booleans. The generator expression below contains only true and false, depending if the item is a number other than one and zero.
if any(i != 0 and i != 1 for i in a):
print "I'll do something here"
Problem is, you were trying to test if the array was not equal to zero and one, thus passing a single Boolean rather than an iterable or generator. You want to test the individual values not the array itself.
Numpy is an overkill and any() is useless. Use Set instead
if set(arr) - set([1,2]):
do something
If you simply want to perform some action for all elements of a that are not (e.g.) 0 or 1, you could filter the array first:
for element in filter(lambda x: x != 0 and x != 1, array):
#dosomething with element
Or, for a more readable version if you're not used to anonymous functions:
def func(a):
return a != 0 and a != 1
for element in filter(func, array):
#dosomething with element
Related
Suppose we have this function:
def search(ls, e):
'''Assumes ls is a list.
Returns True if e is in ls, False otherwise.'''
for i in reversed(range(len(ls))):
if ls[i] == e:
return True
return False
I'm trying to get this function to search through ls starting from the end of the list instead of the beginning. Hence, I included reversed(), which reverses the list, ls.
However, what I'm specifically trying to do is search a list but instead of starting from the index of 0, starting from the index of -1. I don't think reversed() technically does this? If not, how could the function be modified to achieve my objective?
list1 = [1,2,3,4,5]
for i in reversed(range(len(list1))):
print(list1[i])
5
4
3
2
1
it does exactly what you want no?
l2 = [1,2,3,4,5]
for i in range(len(l2)):
print(l2[-i-1])
5
4
3
2
1
you could try something like:
for i in range(len(ls)):
if ls[(-1)*i] == e:
return True
return False
It should start at the back of the list and move forward.
I would actually use enumerate() to do the heavy lifting for you. Using print statements instead of return you can see how it is working better. Basically it creates a physical location index, 0 through the length of the list and allows you to iterate through both the values and the indexes. We do not need the indexes for this, but you have both.
x = [1,2,3,4,5]
for index, value in enumerate(reversed(x)):
if value== 2:
print("TRUE")
else:
print("FALSE")
This first reverses the list, creates enumerated indices and values, assigns the indices iteratively to index and each value (which can be anything a string, a float, another list)to the variable value and in the if else statement compares it to the value (which would be s in your function)
The output is:
FALSE
FALSE
FALSE
TRUE
FALSE
You can see it counted backwards toward 1. I makes seeing what is happening more explicit and allows you to use both the values and the index values of the reversed list without having to slice the original list and keep track of direction.
I have a function here:
def evenlengthchecker(nestedlist):
length = len(nestedlist[0])
for element in nestedlist:
if len(element) != length:
return False
This actually does work when the given nested list contains values. However, when I try something like evenlengthchecker([]), IndexErrors everywhere!
The problem is that your code starts by checking the list at position 0, which is an index error with an empty list. Here's an alternative method that won't give an error:
return (len(set(len(elt) for elt in nestedlist)) <= 1)
This just checks if there is more than one list length in the set of lengths; if you end up with the empty set, no harm done.
def evenlengthchecker(nestedlist):
a = [len(i) for i in nestedlist]
return len(set(a)) ==1
you can use all:
return all(len(x)==len(my_list[0]) for x in my_list)
I'm trying to create a function that returns the largest element of an array, I feel I have the correct code but my syntax is in the wrong order, I'm trying to use a for/while loop in order to do so. So far I have the following:
def manindex(arg):
ans = 0
while True:
for i in range (len(arg)):
if arg[i] > arg[ans]:
pass
ans = i
return ans
Not sure where I'm going wrong if anyone could provide some guidance, thanks
EDIT: So it's been pointing out I'm causing an infinite loop so if I take out the while statement I'm left with
def manindex(arg):
ans = 0
for i in range (len(arg)):
if arg[i] > arg[ans]:
ans = i
return ans
But I have a feeling it's still not correct
When you say array I think you mean list in Python, you don't need a for/loop or while/loop to achieve this at all.
You can also use index with max, like so:
xs.index(max(xs))
sample:
xs = [1,123,12,234,34,23,42,34]
xs.index(max(xs))
3
You could use max with the key parameter set to seq.__getitem__:
def argmax(seq):
return max(range(len(seq)), key=seq.__getitem__)
print(argmax([0,1,2,3,100,4,5]))
yields
4
The idea behind finding the largest index is always the same, iterating over the elements of the array, compare to the max value we have at the moment, if it's better, the index of the current element is the maximum now, if it's not, we keep looking for it.
enumerate approach:
def max_element_index(items):
max_index, max_value = None, None
for index, item in enumerate(items):
if item > max_value:
max_index, max_value = index, item
return max_index
functional approach:
def max_element_index(items):
return reduce(lambda x,y: x[1] > y[1] and x or y,
enumerate(items), (None, None))[0]
At the risk of looking cryptic, the functional approach uses the reduce function which takes two elements and decides what is the reduction. Those elements are tuples (index, element), which are the result of the enumerate function.
The reduce function, defined on the lambda body takes two elements and return the tuple of the largest. As the reduce function reduces until only one element in the result is encountered, the champion is the tuple containing the index of the largest and the largest element, so we only need to access the 0-index of the tuple to get the element.
On the other hand if the list is empty, None object is returned, which is granted on the third parameter of the reduce function.
Before I write a long winded explanation, let me give you the solution:
index, value = max(enumerate(list1), key=lambda x: x[1])
One line, efficient (single pass O(n)), and readable (I think).
Explanation
In general, it's a good idea to use as much of python's incredibly powerful built-in functions as possible.
In this instance, the two key functions are enumerate() and max().
enumerate() converts a list (or actually any iterable) into a sequence of indices and values. e.g.
>>> list1 = ['apple', 'banana', 'cherry']
>>> for tup in enumerate(list1):
... print tup
...
(0, 'apple')
(1, 'banana')
(2, 'cherry')
max() takes an iterable and returns the maximum element. Unfortunately, max(enumerate(list1)) doesn't work, because max() will sort based on the first element of the tuple created by enumerate(), which sadly is the index.
One lesser-known feature of max() is that it can take a second argument in the form max(list1, key=something). The key is a function that can be applied to each value in the list, and the output of that function is what gets used to determine the maximum. We can use this feature to tell max() that it should be ranking items by the second item of each tuple, which is the value contained in the list.
Combining enumerate() and max() with key (plus a little help from lambda to create a function that returns the second element of a tuple) gives you this solution.
index, value = max(enumerate(list1), key=lambda x: x[1])
I came up with this recently (and am sprinkling it everywhere in my code) after watching Raymond Hettinger's talk on Transforming Code into Beautiful, Idiomatic Python, where he suggests exorcising the for i in xrange(len(list1)): pattern from your code.
Alternatively, without resorting to lambda (Thanks #sweeneyrod!):
from operator import itemgetter
index, value = max(enumerate(list1), key=itemgetter(1))
I believe if you change your for loop to....
for i in range (len(arg)):
if arg[i] > ans:
ans = arg[i]
it should work.
You could try something like this. If the list is empty, then the function will return an error.
m is set to the first element of the list, we then iterate over the list comparing the value at ever step.
def findMax(xs):
m = xs[0]
for x in xs:
if x > m:
m = x
return m
findMax([]) # error
findMax([1]) # 1
findMax([2,1]) # 2
if you wanted to use a for loop and make it more generic, then:
def findGeneric(pred, xs):
m = xs[0]
for x in xs:
if pred(x,m):
m = x
return m
findGeneric(lambda a,b: len(a) > len(b), [[1],[1,1,1,1],[1,1]]) # [1,1,1,1]
Both code examples below are old examples of a problem I have where I am iterating through a list of numbers to find numbers that fit a list of conditions but couldn't find a neat way to express it except for:
condition1 and condition2 and condition3 and condition4 and condition5
Two examples of the above:
if str(x).count("2")==0 and str(x).count("4")==0 and str(x).count("6")==0 and str(x).count("8")==0 and str(x).count("0")==0:
if x % 11==0 and x % 12 ==0 and x % 13 ==0 and x%14==0 and x %15 == 0 and x%16==0 and x%17==0 and x%18==0 and x%19==0 and x%20==0:
Is there a simple, more neat way of doing this?
My first retry was to store the conditions in a list like below:
list=["2","4","6","8","0"]
for element in list:
#call the function on all elements of the list
list=[11,12,13,14,15,16,17,18,19,20]
for element in list:
#call the function on all elements of the list
but I was hoping for an even neater/simpler way.
You can use a generator expression like this
def f(n):
return x%n
if all(f(element) for element in lst):
...
If the function/calculation is not too complex, you can just put it inline
if all(x % element for element in lst):
...
The built in function all can simplify this, if you can express your conditions in a generator expression:
result = all(x % n == 0 for n in xrange(11, 21))
It returns a boolean result indicating whether or not all the elements of its iterable argument are True, short-circuiting to end evaluation as soon as one is False.
This is the second question I've seen in the last hour or so for which all is the answer - must be something in the air.
I have a list, or array, called inventory[] and it has a maximum of fifteen entries at any given time. I need to test if any of these entries is equal to zero, and if any one entry is equal to zero, do something. What is an efficient way to do this without doing
if inventory[0] == 0 or inventory[1] == 0 or inventory[2] == 0...
etc.?
For your simple case, I think you could possibly just do this:
if 0 in inventory:
# do something
For a more general case for this type of thing, you can use the any function (docs).
if any([item == 0 for item in inventory]):
# do something
Python's built-in any() function is perfect for this. It takes an iterable as an argument and returns True if any of the elements are true (non-falsy).
if any(item == 0 for item in inventory):
# do something
There is also a similar function called all() that will return True if all elements are True.
Make use of the all function, and the fact that 0 evaluates as False:
if not all(inventory):
...
Edit: assuming that inventory contains only numbers, of course
Try this out:
inventory=[1,2,3,4,0]
if 0 in inventory:
print "There is 0 in the list"
output:
There is 0 in the list