list checking in python - python

Hello there
i've written a small functions that takes two lists and compares them for duplicating pairs,
and returns a boolean value.
For instance ([1,2,3],[2,1,4]) returns false and ([1,2,3],[3,4,5]) returns true
But i would like the argument to take any given amount of lists, instead of just two.
Here's my program so far:
def check(xrr, yrr):
x = xrr[:]
x.sort()
y = yrr[:]
y.sort()
for i in range(len(x)-1):
if x[i]==y[i]:
return False
return True
But also it isnt exactly working correctly yet, as ([1,2,3],[1,4,5]) also returns false.
Any hints and ideas is highly appreciated

import itertools
def check(*args):
r = None
for l in args:
s = set(frozenset(x) for x in itertools.combinations(l, 2))
if r is None:
r = s
else:
r &= s
if not r:
return True
return False
print check([1, 2, 3], [3, 4, 5])
print check([1, 2, 3], [2, 1, 4])

def dupLists(List0,*Lists):
result=set(List0)
for l in Lists:
result=result.intersection(l)
if len(result)<2:
return True
return False

As a naive implementation, you can define a list of lists and hash the internal representation. For instance:
def check(given):
hash = {}
for li in given:
for val in li:
if val in hash:
return False
hash[val] = 1
return True
This works if your input data sets contain a small number of unique elements relative to memory. If you expect to receive extremely large data sets, you might need to consider a more elaborate approach.
Also notable is this will return False for repeating elements within the same data set, and for repeating values at any location within the data set. This is trivial to refactor, or to rewrite entirely as the other solutions listed here.

Related

How to check if a number in a list range

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.

Strictly increasing difference between adjacent elements in a list

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]) )

Check if two tuples have elements in common in their corresponding positions

Here is what I want to do:
pair1 = (1,2)
pair2 = (3,3)
pair3 = (3,2)
# Is there a way that I can compare any of these two objects and yields the following:
def myComp(...):
#...
myComp(pair1,pair2) gives False
myComp(pair1,pair3) gives True #They both have 2 at index 1
myComp(pair1,pair3) gives True #They both have 3 at index 0
Any ideas or advice will be greatly appreciated.
There are builtins to do this much more easily than hardcoding the if statement conditions. You can use zip and any:
def myComp(pair1, pair2):
return any(x == y for x, y in zip(pair1, pair2))
>>> myComp(pair1, pair2)
False
>>> myComp(pair2, pair3)
True
>>> myComp(pair1, pair3)
True
What happens is, the two lists are zipped together using zip which creates a generator of tuples. This is unpacked inside a generator comprehension. any will then test to see if any of the comparisons x == y are True. If yes, the resultant is True and is returned. Else, False is returned.
This approach should work with any arbitrary sized lists, provided they are equal.
Your myComp function just needs an if to do comparison so it would be like:
def myComp(pair1,pair2)
if (pair1[0]==pair2[0] || pair1[1]==pair2[1])
return true;
return false;

Python: general iterator or pure function for testing any condition across list

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

How can I return false if more than one number while ignoring "0"'s?

This is a function in a greater a program that solves a sudoku puzzle. At this point, I would like the function to return false if there is more then 1 occurrence of a number unless the number is zero. What do am I missing to achieve this?
L is a list of numbers
l =[1,0,0,2,3,0,0,8,0]
def alldifferent1D(l):
for i in range(len(l)):
if l.count(l[i])>1 and l[i] != 0: #does this do it?
return False
return True
Assuming the list is length 9, you can ignore the inefficiency of using count here (Using a helper datastructure - Counter etc probably takes longer than running .count() a few times). You can write the expression to say they are all different more naturally as:
def alldifferent1D(L):
return all(L.count(x) <= 1 for x in L if x != 0)
This also saves calling count() for all the 0's
>>> from collections import counter
>>> def all_different(xs):
... return len(set(Counter(filter(None, xs)).values()) - set([1])) == 0
Tests:
>>> all_different([])
True
>>> all_different([0,0,0])
True
>>> all_different([0,0,1,2,3])
True
>>> all_different([1])
True
>>> all_different([1,2])
True
>>> all_different([0,2,0,1,2,3])
False
>>> all_different([2,2])
False
>>> all_different([1,2,3,2,2,3])
False
So we can break this down into two problems:
Getting rid of the zeros, since we don't care about them.
Checking if there are any duplicate numbers.
Striping the zeros is easy enough:
filter(lambda a: a != 0, x)
And we can check for differences in a set (which has only one of each element) and a list
if len(x) == len(set(x)):
return True
return False
Making these into functions we have:
def remove_zeros(x):
return filter(lambda a: a != 0, x)
def duplicates(x):
if len(x) == len(set(x)):
return True
return False
def alldifferent1D(x):
return duplicates(remove_zeros(x))
One way to avoid searching for every entry in every position is to:
flags = (len(l)+1)*[False];
for cell in l:
if cell>0:
if flags[cell]:
return False
flags[cell] = True
return True
The flags list has a True at index k if the value k has been seen before in the list.
I'm sure you could speed this up with list comprehension and an all() or any() test, but this worked well enough for me.
PS: The first intro didn't survive my edit, but this is from a Sudoku solver I wrote years ago. (Python 2.4 or 2.5 iirc)

Categories