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
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.
Is there a way to know which element has failed the any built-in function?
I was trying to solve Euler 5 and I want to find for which numbers my product isn't evenly divisible. Using the for loop it's easy to figure it out, but is it possible with any also?
from operator import mul
primes_under_20 = [2,3,5,7,11,13,17,19]
product = reduce(mul, primes_under_20, 1)
if any((product % i != 0 for i in range(1,21))):
print "not evenly divisible"
# how can I find out that 4 was the element that failed?
# must I use this for loop?
for i in range(1,21):
if product % i != 0:
print i # prints 4
break
I read here that any is equivalent to:
def any(iterable):
for element in iterable:
if element:
return True
return False
but is this the exact implementation, or is there a hiding yield there, or something like this that can help lock on the element?
Is there any good reason to use any?
If you want an one-liner to find out which numbers are not evenly divisible :
not_divisible = [i for i in range(1, 21) if product % i != 0]
if len(not_divisible) > 0:
print(not_divisible)
You can't really get all the non-divisible numbers with any, since it stops when it finds the first False in the iterable
I probably wouldn't recommend actually doing this, as it feels a bit hacky (and uglier than just scrapping the any() for a for loop). That disclaimer aside, this could technically be accomplished by exploiting an iterator and any()'s property of stopping once it's found a truthy value:
rangemax = 21
rng = iter(range(1,rangemax))
if any(product % i != 0 for i in rng):
print "not evenly divisible"
try:
print next(rng) - 1
except StopIteration:
print rangemax - 1
This creates an iterator based on the range(), then runs any(), and if it evaluates True, you check the next item in the iterator (or the max number if you're at the end of the iterator) and subtract one.
For a list I want to recursively count the number of elements that are not v.
My code so far looks like:
def number_not(thelist, v):
"""Returns: number of elements in thelist that are NOT v.
Precondition: thelist is a list of ints
v is an int"""
total = 0
if thelist is []:
return total
elif thelist[0] is v:
print "is v"
total += 0
print total
return number_not(thelist[1:],v)
elif thelist[0] is not v:
print "is not v"
total += 1
print total
return number_not(thelist[1:],v)
return total
It will print the total for each of the individual numbers, but not the final total. For example, for list = [1,2,2,2,1], it will print:
is not v
1
is v
0
is v
0
is v
0
is not v
1
But then my code gets a traceback(list index out of range) error because it keeps going. How do I make it so that it recurses only for the length of the list and that it return the proper total, which for the example is 2
All the code is fine, just the termination condition you have added is not correct,
it should be if not thelist:
Change your code to check the empty list, if thelist is []: to the above.
While the other answers here solve the problem, I don't think they addressed the core issue. The problem is:
if thelist is []:
Because that conditional statement is not what you think it is. For example:
In [2]: [] is []
Out[2]: False
is tests for identity, not equality as you seem to be assuming in your code. It checks the id of an object which is a unique integer which is similar to a memory address in C. Take this example:
In [3]: id([])
Out[3]: 140402932955720
In [4]: id([])
Out[4]: 140402923983176
Each [] is a new object with a unique id, so your base condition would never be triggered. For comparison of list instances you should use == or len (possibly with isinstance if you need to make sure its a list).
As an aside... is is appropriate for comparing constants/builtins like:
1 is 1
type([]) is list
False is False
This is useful when checking something that may be False or an int. If the variable is 0 and you check if not var, False and 0 are both Falsey and would both evaluate to True so you would want to check if var is False and if var is 0 assuming they had different meaning in your code.
Your base case is that the list is empty. Then you want to return 0, right?
Your recursive case requires you to split up your list into the first element and the rest. Check the head of the list -- is it not equal to what you're searching for?
def counter(needle, haystack):
if not haystack:
return 0
# Splits the list into the first element and the remaining elements as a list.
head, *rest = haystack
if head != needle:
return counter(needle, rest) + 1
else:
return counter(needle, rest)
repl.it.
write a function that takes, as an argument, a list called aList. It returns a Boolean True if the list contains each of the integers between 1 and 6 exactly once, and False otherwise.
This is homework and I thought I had it right, but it is now telling me that it isn't right. Here is my code.
def isItAStraight(aList):
count = 0
for i in set(aList):
count += 1
return aList.count(i) == 1
for some reason even if a number appears more than once it still gives true and I can't figure out why it won't give me false unless the first or last number are changed.
Each number has to occur only one time otherwise it is false.
So like take [1,2,3,4,5,6]
would be true.
But [1,2,2,3,4,5]
would be false.
Also, I can't import things like Counter or collections (though it would be so much easier to do it isn't apart of the assignment.)
The list is randomly generated from 1 to 6.
With a return inside the loop, you are only checking one value. You need to check each value. Also, instead of looping through the items of the list, you should loop through the items you're actually looking for. It would also help to make sure there are the correct number of items in the list.
def isItAStraight(aList):
if len(aList) != 6:
return False
for i in range(1, 7):
if aList.count(i) != 1:
return False
return True
But the easiest way to do this is to simply sort the list and check if it's what you're looking for:
def isItAStraight(aList):
return sorted(aList) == list(range(1, 7))
You need to be careful about what's inside the list. What you've written is a basically the same as the pseudo-code below:
let count = 0
for every unique element in aList:
Add 1 to count
if count is now 1, return true.
This will always return true if there is at least one element in aList, since you're adding 1 to count and then returning immediately.
A couple approaches to consider:
Create a 6 element list of all zeros called flags. Iterate over aList and set the corresponding element in flags to 1. If flags is all ones, then you return true.
Sort the list, then check if the first six numbers are 1, 2, 3, 4, 5, 6.
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