Guard clause on lists using only functional programming - python

The problem I am facing is that, given a list and a guard condition, I must verify if every element in the list passes the guard condition.
If even one of the elements fails the guard check, then the function should return false. If all of them pass the guard check, then the function should return true. The restriction on this problem is that I can only use a single return statement.
My code:
def todos_lista(lista, guarda):
for x in lista:
return(False if guarda(x)==False else True)

You should use all:
def todos_lista(lista, guarda):
return all(guarda(x) for x in lista)
Or in a more functional way:
def todos_lista(lista, guarda):
return all(map(guarda, lista))
For example for range 0 to 9 (range(10)):
>>> all(x < 10 for x in range(10))
True
>>> all(x < 9 for x in range(10))
False
>>> all(map(lambda x: x < 9, range(10)))
False
>>> all(map(lambda x: x < 10, range(10)))
True

any will do the job as well:
def todos_lista(lista, guarda):
return not any(not guarda(x) for x in lista)

Related

The Function is breaking before providing all values

def list_num_checker(num_list):
for x in num_list:
if x%2==0:
return x
else:
continue
I just began learning Python and this is the code I have written to create a function to return all the even values in a list. However, It breaks down after checking the first even number.E.g.
list_num_checker([1,2,3,4,5,6])
2
Any and all help is appreciated.
return will cause a function to exit... if you use yield you can make it a generator
def list_num_checker(num_list):
for x in num_list:
if x%2==0:
yield x # yield makes this a generator instead
# else: # you don need the else
# continue
for evennum in list_num_checker([1,2,3,4,5,6,7,8]):
print(evennum)
you could also make a list comprehension
print([x for x in num_list if x%2 == 0])
or you could use the builtin filter function
def is_even(num):
return num % 2 == 0
list(filter(is_even,num_list)) # its a generator so you need to call list on it
I think you can use yield instead of return since return will break the for loop and immediately returns the give value
def list_num_checker(num_list):
for x in num_list:
if x%2==0:
yield x
else:
continue
divisible2 = list(list_num_checker([1,2,3,4,5,6]))
Some possible alternative approaches would be to use list comprehension or filter
def list_num_checker(num_list):
return [x for x in num_list if x % 2 == 0]
def list_num_checker(num_list):
return filter(lambda x: x % 2 == 0, num_list)
return will immediately terminate the function. To produce multiple values in one function, use yield instead.
def list_num_checker(num_list):
for x in num_list:
if x%2==0:
yield x
else:
continue

remove odd numbers from list

when I run the following code, I did not get the correct answer. It returns [4] when it should return [4, 4].
def purify(y):
new_numbers = []
for x in y:
if x%2 ==0:
new_numbers.append(x)
return new_numbers
print(purify([4,5,5,4]))
Your indent is off, place the return after the for loop runs
def purify(y):
new_numbers = []
for x in y:
if x%2 ==0:
new_numbers.append(x)
return new_numbers
Use some elegant expressions like list comprehension combined with if something like this
def purify(y):
return [x for x in y if x%2 == 0]
You should be careful with indentation when working with Python as below code is good but there is an issue with indentation on return new_numbers.
return new_numbers is aligned with if condition due to which for loop only runs once and returns the first 4. If you indent return statement with for loop it will work perfectly.
def purify(y):
new_numbers = []
for x in y:
if x%2 ==0:
new_numbers.append(x)
return new_numbers
print(purify([4,5,5,4]))
You can do this in just one line:
def purify(y):
return [x for x in y if not x%2]
just use lamda :
def purify(y):
filter(lambda i: not i%2==0, y)

Python, check if sets check out

I have made the function, but I need to make a guess so it will run through the function and check if it fits, if not, start over again with new numbers.
If I find a set that works, the loop should break, the problem is that I am new to python and math programming.
def checkStuff(X):
ok = True
#i.
if(min(X) <= 0):
ok = False
#ii.A
A = set()
for x in X:
A.add(x % 2)
#ii.B
B = set()
for y in X:
B.add(y**2)
#ii.C
C = set()
for z in X & B:
C.add(z**0.5)
#ii.D
D = set()
for w in C:
D.add(w**2)
#iii.
if(len(X)<=0):
ok = False
#iv.
if(len(X) not in X):
ok = False
#v.
if len(A) in X:
ok = False
#vi.
if sum(X) not in B:
ok = False
#vii.
if sum(X&B) in B:
ok = False
#viii.
if sum(C.union(D)) not in X:
ok = False
return ok
without giving you the exact code, try looking at the while loop and the random function
Your function can be simplified and optimized, returning as soon as possible, avoiding further computations... for compactness I used set comprehensions instead of your loops
def checkStuff(X):
if(min(X) <= 0): return False
if(len(X)<=0): return False
if(len(X) not in X): return False
A = {x % 2 for x in X}
if len(A) in X: return False
B = {x**2 for x in X}
if sum(X) not in B: return False
if sum(X&B) in B: return False
C = {xb**0.5 for xb in X&B}
D = {c**2 for c in C}
if sum(C.union(D)) not in X: return False
return True
Assuming that you have a function that returns a list of trial sets or, possibly better, yields a new trial set for each loop, and that you want to use ONLY the first X that matches your conditions, then you can write your stuff like this
for X in generate_trial_sets():
if checkStuff(X):
do_stuff(X)
break
else:
print("No X was generated matching the criteria")
...
Note that the else clause is aligned correctly, because Python has a for ... else .. control flow construct.
Blind Attempt at a generate_trial_sets Function
Given that each X is a set of numbers (integers? reals? complex numbers? who knows? you, but you didn't care to tell...) and that we don't know how many numbers you want in the set, and also that you want to stop the iteration somehow, I'd write
def generate_trial_sets(nmin=1, nmax=5,
xmin=0.0, xmax=10.0, iterations=10):
from random import randint
for _ in range(iterations):
n = randint(nmin,nmax+1)
x = {n}
for i in range(1,n):
x.add((xmax-xmin)*random()+xmin)
yield x
When you call it like
for X in generate_trial_sets():
without modifying the default args, you get back 10 sets of length comprised between 1 and 5, with real values comprised between 0 and 10 (one of the values is equal to the length, so one of your tests is automatically fulfilled).
To use different parameters, specify them at the invocation:
for X in generate_trial_sets(nmin=6,nmax=6,xmax=100.0,iterations=200):
This is not a solution of your problem but if you understand the logic you'll get started in the right direction or, at least, I hope so...

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)

Does Python have an "or equals" function like ||= in Ruby?

If not, what is the best way to do this?
Right now I'm doing (for a django project):
if not 'thing_for_purpose' in request.session:
request.session['thing_for_purpose'] = 5
but its pretty awkward. In Ruby it would be:
request.session['thing_for_purpose'] ||= 5
which is much nicer.
Jon-Eric's answer's is good for dicts, but the title seeks a general equivalent to ruby's ||= operator.
A common way to do something like ||= in Python is
x = x or new_value
Precise answer: No. Python does not have a single built-in operator op that can translate x = x or y into x op y.
But, it almost does. The bitwise or-equals operator (|=) will function as described above if both operands are being treated as booleans, with a caveat. (What's the caveat? Answer is below of course.)
First, the basic demonstration of functionality:
x = True
x
Out[141]: True
x |= True
x
Out[142]: True
x |= False
x
Out[143]: True
x &= False
x
Out[144]: False
x &= True
x
Out[145]: False
x |= False
x
Out[146]: False
x |= True
x
Out[147]: True
The caveat is due python not being strictly-typed, and thus even if the values are being treated as booleans in an expression they will not be short-circuited if given to a bitwise operator. For example, suppose we had a boolean function which clears a list and returns True iff there were elements deleted:
def my_clear_list(lst):
if not lst:
return False
else:
del lst[:]
return True
Now we can see the short-circuited behavior as so:
x = True
lst = [1, 2, 3]
x = x or my_clear_list(lst)
print(x, lst)
Output: True [1, 2, 3]
However, switching the or to a bitwise or (|) removes the short-circuit, so the function my_clear_list executes.
x = True
lst = [1, 2, 3]
x = x | my_clear_list(lst)
print(x, lst)
Output: True []
Above, x = x | my_clear_list(lst) is equivalent to x |= my_clear_list(lst).
dict has setdefault().
So if request.session is a dict:
request.session.setdefault('thing_for_purpose', 5)
Setting a default makes sense if you're doing it in a middleware or something, but if you need a default value in the context of one request:
request.session.get('thing_for_purpose', 5) # gets a default
bonus: here's how to really do an ||= in Python.
def test_function(self, d=None):
'a simple test function'
d = d or {}
# ... do things with d and return ...
In general, you can use dict[key] = dict.get(key, 0) + val.

Categories