I have this silly interest in how to avoid the following error in a smart way (possibly using the right numpy functions).
In many ocasions I need to use the numpy where function to find a single item. However, sometimes this item is present more than once, I would like to use the indeces from the where function in a way in which the output would be an simple variable (if it appears once, either string or float) or an array (if mutiple instances).
Of course, I could use len() in a boolean check and perform the conversion. However, I would like to know if there is a one step approach. I had tought to use asscalar however, this function returns and error if the input is not a 1 value array (I had hope it would return the input value unchanged :/). Here is the reproduction of the error on the second part of the code
import numpy as np
Inventory = np.array(['Eggs', 'Milk', 'Ham', 'Eggs'])
Drinks = 'Milk'
Food = 'Eggs'
index_item_searched = np.where(Inventory == Drinks)
items_instore = np.asscalar(Inventory[index_item_searched])
print 'The shop has', items_instore
index_item_store = np.where(Inventory == Food)
items_instore = np.asscalar(Inventory[index_item_store])
print 'The shop has', items_instore
#I want an output like ['Eggs', 'Eggs']
Thanks for your patience :)
If I understand correctly that you want to print a scalar in case of a single find in the Inventory
, while you want to print an array in case of multiple finds, then the answer is " this is not a nice thing to do ", and is generally considered poor design. In other words, there's a reason why this can't be done without a bit of work: it can be dangerous if your code produces different kinds of results based on semantics.
Anyway, one of the answers by @kindall to the already linked question suggests a function
def scalify(l):
return l if len(l) > 1 else l[0]
which will return the list given to it, unless the list has a single element in which case it returns the element. Just what you
need
want.
Example:
import numpy as np
def scalify(l):
return l if len(l) > 1 else l[0]
def getitems(inventory,itemtype):
return inventory[inventory==itemtype]
Inventory = np.array(['Eggs', 'Milk', 'Ham', 'Eggs'])
Drinks = 'Milk'
Food = 'Eggs'
print('The shop has %s' % scalify(getitems(Inventory,Drinks)))
print('The shop has %s' % scalify(getitems(Inventory,Food)))
Output:
The shop has Milk
The shop has ['Eggs' 'Eggs']
For future reference:
As of numpy v1.16, asscalar
is deprecated. Use np.ndarray.item
instead. As the other answer said, generally it's nicer for functions to only return a single type, but there are notable APIs where this is not the case (like __getitem__
for numpy arrays and even lists!). So I would recommend
from typing import Union, Any
import numpy as np
def maybe_single_item(array: np.ndarray) -> Union[np.ndarray, Any]:
try:
return array.item()
except TypeError:
return array
(python 3.5+)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.