I have a dict
x={1:1,2:2,3:8,4:8,5:2,6:7,7:4,8:9,10:2}
I want to define a function f(i) that returns the key having the value i.
Now that multiple keys have the same values, the min key should be returned.
Ex-
i=2
then in x, 2,5 and 10 has value i=2
So 2 must be returned.
i=8
3 and 4 have value 8 then 3 must be returned.
Is it possible to do this without using loops, as this function act as a base function and will be called from other function multiple times ( approx up to 10^18 )? I want to write this function without a loop. Is it possible?
Make use of min and dict comprehnesion
def find(i):
return min({k:v for k,v in x.items() if v == i}.keys())
print(find(2))
output
2
The easiest would be
def f(dictionary, target_value):
return min(filter(lambda k: dictionary[k] == target_value, dictionary.keys()))
One way to do it without directly using loops, is to use the filter() function along with the min():
x={1:1,2:2,3:8,4:8,5:2,6:7,7:4,8:9,10:2}
def f(i):
global x
return min(filter(lambda k: x[k] == i, x))
NOTE: Although I use global to be able to use x inside f(), it is better to add one more argument in f() to avoid globals:
def f(x, i):
return min(filter(lambda k: x[k] == i, x))
Testing it with the examples you provided in your question:
print(f(2))
print(f(8))
will return:
2
3
This would definitely work fine in your case try the below solution
def findMinIndexElement(to_find):
values = list(x.values())
keys = list(x.keys())
try:
return keys[values.index(to_find)]
except:
return 'Not Found'
x={1:1,2:2,3:8,4:8,5:2,6:7,7:4,8:9,10:2, 11:7}
to_find = int(input())
print(findMinIndexElement(to_find))
Related
I was wondering if there was a simple alternative to lambda in my code.
def add_attack(self, attack_name):
if attack_name in self.known_attacks and attack_name not in self.attacks:
try:
assert(len(self.attacks) < 4)
self.attacks[attack_name] = self.known_attacks.get(attack_name)
return True
except:
#find the min value of self.attacks
minval = min(self.attacks.keys(), key=(lambda k: self.attacks[k]))
for keys, values in self.attacks.items():
if self.attacks[minval] == values and min(minval, keys) == keys:
minval = keys
del self.attacks[minval]
self.attacks[attack_name] = self.known_attacks.get(attack_name)
return True
else:
return False
I'm still learning python, and the lambda function is throwing me off since I haven't learned that much about it yet. Instead of using lambda, can someone help me out with another function to replace lambda? Thanks!
You could define a function for it:
def return_attacks(self,k):
return self.attacks[k]
And use that function in the key:
minval = min(self.attacks.keys(), key=(self.return_attacks))
I would strongly recommend you get comfortable with lambda functions - and I think it is clear to you now that lambda x : expr(x) is equivalent to func when
def func(x):
return expr(x)
A lambda should not scare you! It's just a small anonymous function.
It can take any number of arguments, but can only have one expression.
minval = min(self.attacks.keys(), key=(lambda k: self.attacks[k]))
Here you are getting the result of the expression min() as minval
The min function can take keys, here is more about that. I can see it can be confusing, but this key is not the same thing with a dictionary key. This key is just a way to tell the min function how it should behave.
If we go back to the code:
So the line basically finds the minimum value in self.attacks.keys(), with a lambda function that returns every element in self.attacks[]
If you do not want to use lambda, you can write a function in your class that does exactly the same thing.
def find_min_key(self, my_dict):
return min(my_dict, key= my_dict.get)
You can use this as:
min_val = self.find_min_key(self.attacks)
I have a float number x and a list range list_ = [[a, b], [c,d], [e,f]]
How can check if the number x is in the list. It means the function will return True in case of
a<=x <=b
or
c<=x <=d
or
e<=x <=f
Otherwise, the function will return False. Could you help me to write a Python code for the function
function (x, list_)--> True/False
Clean solution:
def function(x, list_):
return any([l[0] < x < l[1] for l in list_])
Optimized solution:
def function(x, list_):
for l in list_:
if l[0] < x < l[1]:
return True
return False
The idiomatic solution would be this:
def f(x: int, ls: List[Tuple[float, float]]) -> bool:
return any(a <= x <=b for (a, b) in ls)
Take specific note of the following:
Naming a function function is a super poor idea.
It is abnormal and therefore a poor idea to name a variable list_ just to avoid overriding a keyword.
Using the form any ensures that you quickly quit when you find a valid solution.
You can quickly destructure your tuple (or list, if you happen to pass a list) using the for (a, b) in ls clause.
This solution is as quick as if you use a for clause, but all of that is premature optimization anyway.
Using an explicit destructing ensures you have two and only two elements for your sublist.
It was requested that I check certain inputs:
>>> f(10.1, [[8.1, 12.1], [110, 120]])
True
Seems to work!
If you're running into NameError, the issue is simply one of the importation of types. You can either define f like so:
def f(x, ls):
... // As you would otherwise
Or import the required types to make the type-hinting work properly:
from typing import List, Tuple
def f(x: int, ls: List[Tuple[float, float]]) -> bool:
... // As you would otherwise
This has little to do with the original question or solution - it's just standard for type hinting in python.
def function(x,list__):
for [a,b] in list_data:
if a<=x<=b:
return True
return False
You can simply iterate through the list and find whether it's in range or not.
I'm generating the variable and the list randomly and calling a function that iterates and checks whether the variable lies within the range of any of the members of the list.
import numpy as np
def find_if_in_range(list_, var) -> bool:
for i in list_:
if i[0] <= var <= i[-1]:
return True
return False
var = np.random.randint(10)
list_ = np.random.randint(10, size=(3,2), dtype=np.uint8)
print(f"var: {var}")
print(f"list: {list_}")
res = find_if_in_range(list_, var)
print(res)
Output:
var: 0
list: [[0 6]
[2 7]
[7 9]]
True
Hope this helps.
Cheers.
my code consists of me recreating the function 'filter()' and using it with a function to filter words longer than 5 characters. It worked with the actual function filter when I tried it btw...I'm using python 3+
def filter1(fn, a):
i = 0
while i != len(a):
u = i - 1
a[i] = fn(a[i], a[u])
i += 1
return a
def filter_long_words(l):
if len[l] > 5:
return [l]
listered = ['blue', 'hdfdhsf', 'dsfjbdsf', 'jole']
print(list(filter1(filter_long_words, listered)))
getting error
TypeError: filter_long_words() takes 1 positional argument but 2 were given
You are passing two parameters to fn (which refers to filter_long_words) here:
a[i] = fn(a[i], a[u])
But filter_long_words only accepts one parameter.
Notes:
You can loop through lists using for item in my_list, or if you want index as well for index, item in enumerate(my_list).
I think you might get an IndexError since u will be -1 in the first round of your loop.
The filter function can also be expressed as a list comprehension: (item for item in listered if filter_long_words(item))
My version of filter would look like this, if I have to use a for loop:
def my_filter(fn, sequence):
if fn is None:
fn = lambda x: x
for item in sequence:
if fn(item):
yield item
Since you have stated that you are using Python 3, this returns a generator instead of a list. If you want it to return a list:
def my_filter(fn, sequence):
if fn is None:
fn = lambda x: x
acc = []
for item in sequence:
if fn(item):
acc.append(item)
return acc
If you don't need to use a for loop:
def my_filter(fn, sequence):
if fn is None:
fn = lambda x: x
return (item for item in sequence if fn(item))
Your're calling fn with 2 parameters in filter1(fn, a), and since you've passed filter_long_words() to filter1 as fn, that triggers the error.
But there's more weird stuff:
I don't understand the magick of filter1 or what you were trying to
accomplish, but it seems to me that you don't have a clear idea what to do.
But if you want to mimic (somehow) how filter works, you have to return a
list which contains only items for which the fn function returns true. When
you know this, you can rewrite it - here are a few suggestions for rewrite
# explicit, inefficient and long, but straightforward version:
def filter1(fn, a):
new_list = []
for item in a:
if fn(item):
new_list.append(item):
return new_list
# shorter version using list comprehensions:
def filter1(fn, a):
return [item for item in a if fn(item)]
The filter_long_words function is wrong too - it should return True or
False. The only reason why it could work is because any non-empty list is
treated as True by python and default return value of a function is None,
which translates to False. But it's confusing and syntactically wrong to use
len[l] - the proper usage is len(l).
There are a few suggestions for rewrite, which all returns explicit boolean
values:
# unnecessary long, but self-explanatory:
def filter_long_words(l):
if len(l) > 5:
return True
else
return False
# short variant
def filter_long_words(l):
return len(l) > 5
You are calling "filter_long_words" with 2 parameter => fn(a[i], a[u]) also there is an error
def filter_long_words(l):
if **len[l]** > 5:
return [l]
len is builtin method it should be len(l)
I know there are easier ways to create a function which gives you the largest number in a list of numbers but I wanted to use recursion. When I call the function greatest, i get none. For example greatest([1,3,2]) gives me none. If there are only two elements in the list, I get the right answer so I know the problem must be with the function calling itself. Not sure why though.
def compare(a,b):
if a==b:
return a
if a > b:
return a
if a < b:
return b
def greatest(x):
if len(x)==0:
return 0
i=0
new_list=[]
while i< len(x):
if len(x)-i>1:
c=compare(x[i],x[i+1])
else:
c=x[i]
new_list.append(c)
i=i+2
if len(new_list)>1:
greatest(new_list)
else:
return new_list[0]
print greatest([1,3,2])
This line:
if len(new_list)>1:
greatest(new_list) # <- this one here
calls greatest but doesn't do anything with the value it returns. You want
return greatest(new_list)
After fixing that, your function seems to behave (although I didn't look too closely):
>>> import itertools
>>> for i in range(1, 6):
... print i, all(max(g) == greatest(g) for g in itertools.product(range(-5, 5), repeat=i))
...
1 True
2 True
3 True
4 True
5 True
A simple recursion can be like this :
from random import *
def greatest(x,maxx=float("-inf")):
if len(x)>0:
if x[0] > maxx:
maxx=x[0]
return greatest(x[1:],maxx)
else:
return maxx
lis=range(10,50)
shuffle(lis)
print greatest(lis) #prints 49
Basic stuff I know...;-P But what is the best way to check if a function returns some values?
def hillupillu():
a= None
b="lillestalle"
return a,b
if i and j in hillupillu(): #how can i check if i or j are empty? this is not doing it of course;-P
print i,j
If you meant that you can't predict the number of return values of some function, then
i, j = hillupillu()
will raise a ValueError if the function doesn't return exactly two values. You can catch that with the usual try construct:
try:
i, j = hillupillu()
except ValueError:
print("Hey, I was expecting two values!")
This follows the common Python idiom of "asking for forgiveness, not permission". If hillupillu might raise a ValueError itself, you'll want to do an explicit check:
r = hillupillu()
if len(r) != 2: # maybe check whether it's a tuple as well with isinstance(r, tuple)
print("Hey, I was expecting two values!")
i, j = r
If you meant that you want to check for None in the returned values, then check for None in (i, j) in an if-clause.
Functions in Python always return a single value. In particular they can return a tuple.
If you don't know how many values in a tuple you could check its length:
tuple_ = hillupillu()
i = tuple_[0] if tuple_ else None
j = tuple_[1] if len(tuple_) > 1 else None
After receiving the values from the function:
i, j = hillupillu()
You can check whether a value is None with the is operator:
if i is None: ...
You can also just test the value's truth value:
if i: ...
if(i == "" or j == ""):
//execute code
something like that should wordk, but if your giving it a None value you would do this
if(i == None or j == None):
//execute code
hope that helps
You can check whether the return value of the function is a tuple:
r_value = foo(False)
x, y = None, None
if type(r_value) == tuple:
x, y = r_value
else:
x = r_value
print(x, y)
This example is suited for a case where the function is known to return either exactly one tuple of length 2 (for example by doing return a, b), or one single value. It could be extended to handle other cases where the function can return tuples of other lengths.
I don't believe #Fred Foo's accepted answer is correct for a few reasons:
It will happily unpack other iterables that can be unpacked into two values, such as a list or string of lengths 2. This does not correspond to a return from a function that returned multiple values.
The thrown exception can be TypeError, not a ValueError.
The variables that store the return value are scoped to the try block, and so we can only deal with them inside that block.
It doesn't show how to handle the case where there is a single returned value.