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.
Related
Write a function expanding(l) that takes as input a list of integer l and returns True if the absolute difference between each adjacent pair of elements strictly increases.
I tried to execute this code but this isn't returning correct value for some lists.
def expanding(l):
for i in range(0,len(l)-3):
if (abs(l[i+2]-l[i+1])>abs(l[i+1]-l[i])):
Answer=True
else:
Answer=False
return Answer
expanding([1,3,7,2,-3]) should be False but the output is True.
Use a temporary variable to store the difference, and exit once you reach a non-increasing difference.
def expanding(l):
dif = abs(l[1] - l[0])
for i in range(1, len(l)-1):
temp = abs(l[i+1] - l[i])
# Non-increasing difference, return
if temp < dif:
return False
else:
dif = temp
# All differences are increasing
return True
Yet another solution using iterators:
from itertools import tee, islice, starmap
from operator import lt, sub
def pairwise(x):
a, b = tee(x, 2)
return zip(a, islice(b, 1, None))
a = [1,3,7,2,-3]
pairs = pairwise(a) # this will be (a[0], a[1]), (a[1], a[2]), ...
# The next will produce the result abs(a[1]-a[0]), abs(a[2]-a[1]), ...
differences = map(abs, starmap(sub, pairs))
# This will be abs(a[2]-a[1])>abs(a[1]-a[0]), abs(a[3]-a[2])>abs(a[2]-a[1]), ...
cmp = starmap(lt, pairwise(differences))
# Differences strictly increases if all items in cmp are evaluated to True...
result = all(cmp)
print(result)
The output for such input is False
Numpy is your friend:
import numpy as np
x=np.array([1,3,7,2,-3])
(np.diff(abs(x[1:] - x[:-1])) > 0).all() # returns False
If you're fancy a function, I would do like this:
def expanding(l):
# convert list to np.array if a list was passed
if isinstance(l, list):
l = np.array(l)
return (np.diff(abs(l[1:] - l[:-1])) > 0).all()
I would recommend writing the condition in an iterator that you then pass to any so to make sure that on the first occurrence of a non-expanding difference the iteration stops and False is returned.
Here is how this would look:
def expanding(l):
return not any((abs(l[i-1]-l[i])>=abs(l[i]-l[i+1]) for i in range(1,len(l)-1)))
def expanding(L):
x=list()
for i in range(len(L)-2):
if abs(L[i+1]-L[i+2]) > abs(L[i]-L[i+1]):
x.append(True)
else:
x.append(False)
return all(x)
print(expanding([1,3,7,2,9]))
Output:
True
Explanation:
when we calculate difference list for the given list -> [2,4,5,7]
The difference list is strictly increasing.
Print(expanding([1,3,7,2,-3]))
Output:
False
Explanation:
when we calculate difference list for the given list -> [2,4,5,5]
The difference list is not increasing (i.e., 5>5 is False)
def expanding(l):
for i in range(0,len(l)-2):
if (abs(l[i+2]-l[i+1])>abs(l[i+1]-l[i])):
Answer=True
else:
Answer=False
return Answer
return Answer
expanding([1,3,7,2,-3])
As soon as you know that one item is out of order you should answer False for the whole list without waiting,so that other pairs not change the answer.
Also note the change from range(0,len(l)-3) to range(0,len(l)-2). The original implementation was missing the last pair of list elements.
Your logic is a little bit wrong. Once you know that one item is out of order you should answer False for the whole list.
def expanding(l):
for i in range(0,len(l)-3):
if (abs(l[i+2]-l[i+1])<=abs(l[i+1]-l[i])):
return False
return True
Code Written By Debkanta Mondal
Python3
def expanding(l):
dif=[]
for x,y in zip(l,l[1:]):
diff=abs(y-x)
dif.append(diff)
return all(i<j for i,j in zip(dif,dif[1:]))
print(expanding([1,3,7,2,-3]) )
Sorry for for the potentially silly question. But this seems to be a stumping problem I just can't find the answer to.
Say I have the following mixed nested list in python:
a = [((1,1),(0,0)), (3,4)]
I'd like to check if the following tuples b, c and d appear in a:
b = (1,1)
c = (0,0)
d = (3,4)
print(b in a) # <- False ?
print(c in a) # <- False ?
print(d in a) # <- True
I'd like to replace the code in each print statement in such away that the search finds the tuple in the list and as such returns True
Any help at all would be much appreciated. Apologies if this question has already been asked before.
We need a recursive function that takes a list or tuple and an element to find.
Each function should check whether the element is in the current iterable using the in operator. If it is in then return True, otherwise check if it is in any of the lower dimensions by recursively calling itself with each of the lower iterables and return if any of those succeeded (this can be done with a for-loop, but we may as well use the any() function).
So a one liner would be roughly:
def inc(it, e):
return True if e in it else any(inc(iit, e) for iit in it if type(iit) in (list, tuple))
And it works as intended:
>>> inc(a, (1,1))
True
>>> inc(a, (0,0))
True
>>> inc(a, (3,4))
True
The list has two elements, a tuple which contains other tuples, and a tuple of ints. If you want to check the nested structures, you are going to have to do that yourself. A recursive solution (this one assumes the nested containers can only be either tuple's or lists) would be one option if nesting can be arbitrarily deep:
>>> a = [((1,1),(0,0)), (3,4)]
>>> def is_in(x, nested):
... result = False
... if not isinstance(nested, (tuple, list)):
... return result
... for item in nested:
... if x == item:
... result = True
... else:
... result = result or is_in(x, item)
... if result:
... return True
... return result
...
>>> is_in((1,1), a)
True
>>> is_in((0,0), a)
True
>>> is_in((3,4), a)
True
>>> is_in((8, 8), a)
False
>
This should stop traversing once the first match is found.
Note, if recursion isn't your thing, you can replace the call stack with your own stack!
def is_in_iterative(x, nested):
stack = [nested]
while stack:
item = stack.pop()
print(item)
if item == x:
return True
elif isinstance(item, (list, tuple)):
stack.extend(item)
return False
However, note that this will check in the reverse order...
i tried to solve your problem by recursive function method and global variable defining , i wish this solution can give you idea:
a = [((1,1),(0,0)), (3,4)]
global bb
bb=False
def checker(tuple1, tuple2):
b=str(type(('a','b')))
for i in range(len(tuple1)):
if(str(type(tuple1[i]))!=b):
if (tuple1==tuple2):
global bb
bb=True
else:
checker(tuple1[i],tuple2)
checker(a,(1,1))
print(bb)
#-->True
bb=False
checker(a,(3,4))
print(bb)
#-->True
bb=False
checker(a,(0,0))
print(bb)
#--->True
bb=False
checker(a,(10,1))
print(bb)
#--->False
I would like to have a function AllTrue that takes three arguments:
List: a list of values
Function: a function to apply to all values
Condition: something to test against the function's output
and return a boolean of whether or not all values in the list match the criteria.
I can get this to work for basic conditions as follows:
def AllTrue(List, Function = "Boolean", Condition = True):
flag = True
condition = Condition
if Function == "Boolean"
for element in List:
if element != condition:
flag = False
break
else:
Map = map(Function, List)
for m in Map:
if m != condition:
flag = False
break
return flag
Since python doesn't have function meant for explicitly returning if something is True, I just make the default "Boolean". One could clean this up by defining TrueQ to return True if an element is True and then just mapping TrueQ on the List.
The else handles queries like:
l = [[0,1], [2,3,4,5], [6,7], [8,9],[10]]
AllTrue(l, len, 2)
#False
testing if all elements in the list are of length 2. However, it can't handle more complex conditions like >/< or compound conditions like len > 2 and element[0] == 15
How can one do this?
Cleaned up version
def TrueQ(item):
return item == True
def AllTrue(List, Function = TrueQ, Condition = True):
flag = True
condition = Condition
Map = map(Function, List)
for m in Map:
if m != condition:
flag = False
break
return flag
and then just call AllTrue(List,TrueQ)
Python already has built-in the machinery you are trying to build. For example to check if all numbers in a list are even the code could be:
if all(x%2==0 for x in L):
...
if you want to check that all values are "truthy" the code is even simpler:
if all(L):
...
Note that in the first version the code is also "short-circuited", in other words the evaluation stops as soon as the result is known. In:
if all(price(x) > 100 for x in stocks):
...
the function price will be called until the first stock is found with a lower or equal price value. At that point the search will stop because the result is known to be False.
To check that all lengths are 2 in the list L the code is simply:
if all(len(x) == 2 for x in L):
...
i.e. more or less a literal translation of the request. No need to write a function for that.
If this kind of test is a "filter" that you want to pass as a parameter to another function then a lambda may turn out useful:
def search_DB(test):
for record in database:
if test(record):
result.append(record)
...
search_DB(lambda rec: all(len(x) == 2 for x in rec.strings))
I want a function that takes a list, a function, and a condition, and tells me if every element in the list matches the condition. i.e. foo(List, Len, >2)
In Python >2 is written lambda x : x>2.
There is (unfortunately) no metaprogramming facility in Python that would allow to write just >2 or things like ยท>2 except using a string literal evaluation with eval and you don't want to do that. Even the standard Python library tried going down that path (see namedtuple implementation in collections) but it's really ugly.
I'm not saying that writing >2 would be a good idea, but that it would be nice to have a way to do that in case it was a good idea. Unfortunately to have decent metaprogramming abilities you need a homoiconic language representing code as data and therefore you would be programming in Lisp or another meta-language, not Python (programming in Lisp would indeed be a good idea, but for reasons unknown to me that approach is still unpopular).
Given that, the function foo to be called like
foo(L, len, lambda x : x > 2)
is just
def foo(L, f=lambda x : x, condition=lambda x: x):
return all(condition(f(x)) for x in L)
but no Python programmer would write such a function, because the original call to foo is actually more code and less clear than inlining it with:
all(len(x) > 2 for x in L)
and requires you to also learn about this thing foo (that does what all and a generator expression would do, just slower, with more code and more obfuscated).
You are reinventing the wheel. Just use something like this:
>>> l = [[0,1], [2,3,4,5], [6,7], [8,9],[10]]
>>> def all_true(iterable, f, condition):
... return all(condition(f(e)) for e in iterable)
...
>>> def cond(x): return x == 2
...
>>> all_true(l, len, cond)
False
You can define a different function to check a different condition:
>>> def cond(x): return x >= 1
...
>>> all_true(l, len, b)
True
>>>
And really, having your own function that does this seems like overkill. For example, to deal with your "complex condition" you could simply do something like:
>>> l = [[0,2],[0,1,2],[0,1,3,4]]
>>> all(len(sub) > 2 and sub[0] == 5 for sub in l)
False
>>> all(len(sub) > 1 and sub[0] == 0 for sub in l)
True
>>>
I think the ideal solution in this case may be:
def AllTrue(List, Test = lambda x:x):
all(Test(x) for x in List)
This thereby allows complex queries like:
l = [[0, 1], [1, 2, 3], [2, 5]]
AllTrue(l, lambda x: len(x) > 2 and x[0] == 1)
To adhere to Juanpa's suggestion, here it is in python naming conventions and an extension of what I posted in the question now with the ability to handle simple conditions like x > value.
from operator import *
all_true(a_list, a_function, an_operator, a_value):
a_map = map(a_function, a_list)
return all( an_operator(m, a_value) for m in a_map)
l = [[0,2],[0,1,2],[0,1,3,4]]
all_true(l, len, gt, 2)
#True
Note: this works for single conditions, but not for complex conditions like
len > 2 and element[0] == 5
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)
Exercise:
Write a function called is_sorted that takes a list as a parameter and returns True if the list is sorted in ascending order and False otherwise. You can assume (as a precondition) that the elements of the list can be compared with the relational operators <, >, etc.
For example, is_sorted([1,2,2]) should return True and is_sorted(['b', 'a']) should return False.
So far I have:
def is_sorted(stuff):
for i in stuff:
if stuff[i+1] > stuff[i]:
return True
else:
return False
numbers = [1, 0, 5, 2, 8]
print is_sorted(numbers)
But it seems to return True every time I change the numbers list around. How do I change this so it works?
The line
for i in stuff:
Iterates through items, not indices. If you put 5 or 8 first, you will get an IndexError. Also, you return if the check passes for the first item, much too early! You can return False if any are out of order, but all must be in order to return True.
Instead, try using enumerate to get both item and index:
def is_sorted(stuff):
for index, item in enumerate(stuff):
try:
if item > stuff[index + 1]:
return False
except IndexError:
return True
Alternatively, use zip to compare pair wise:
def is_sorted(stuff):
return all(b >= a for a, b in
zip(stuff, stuff[1:]))
for i in stuff will enumerate each of the elements. What you'd like to do is enumerate the indices of the elements, so change the loop to
for i in range(len(stuff))
Next, you dont want to return True if you come across a subsequent element greater than the current. just return True after testing each pair of adjacent elements, so something like:
def is_sorted(stuff):
for i in range(1,len(stuff)):
if stuff[i - 1] > stuff[i]:
return False
return True
Building off #jonrsharpe's answer,
This is a great application of the itertools pairwise recipe:
from itertools import tee, izip
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None) #or b.next() on Python 2.5 and below
return izip(a, b)
def is_sorted(iterable):
return all(a <= b for a,b in pairwise(iterable))
This avoids indexed access or slicing, which allows you to operate on generators and greatly reduces memory footprint.
is_sorted(xrange(5000000))
Unfortunately, it won't help you for infinite generators like is_sorted(count(0))
It looks like you're conflating for item in stuff with for i in range(len(stuff)).
Say stuff = ['a', 'b', 'c', 'd'].
With for item in stuff, you'd be iterating over each item in stuff: 'a', 'b', 'c', and 'd'.
With for i in range(len(stuff)), you'd be iterating over each index of stuff: 0, 1, 2, 3.
Note that the variable names item and i are common conventions for these statements but are not mandatory--you can replace item and i with anything you want. Therefore your 2nd line of code (for i in stuff) is executing #1 above, not #2 as you were expecting.
To have your code execute #2, you'd have to use range(len(stuff) in your 2nd line of code instead of just stuff.
I know this is an old thread but I am trying to refine my solution to this problem.
I want to make sure no body sneaks in an integer or a string in a predominantly string or integer list resp. For instance, ['a', 'b', 2]
I wrote a python program for this but it seems to me it is getting a bit unwieldy. Is there any better solution to this?
def is_sorted(stuff):
is_int = 1
not_int = 0
if type(stuff[0]) == int:
of_type = is_int
else:
of_type = not_int
for i in range(1,len(stuff)):
if (of_type == is_int and (type(stuff[i - 1]) == int and type(stuff[i]) == int)) or \
(of_type == not_int and (type(stuff[i - 1]) == str and type(stuff[i]) == str)):
if stuff[i - 1] > stuff[i]:
return False
else:
print "I saw what you did there!"
return False
return True
print is_sorted(['b', 'a']) //False
print is_sorted(['a', 'b']) //True
print is_sorted([1, 2]) //True
print is_sorted(['a', 'b', 2]) //False; "I saw what you did there!"
def isSorted(stuff):
if len(stuff) == 0:
output = 'True'
if len(stuff) == 1:
output = 'True'
for i in range(0,len(stuff)-1):
if stuff[i+1] > stuff[i]:
output = 'True'
else:
return False
return output