How to check through an entire list in Python for a condition fulfillment - list

So I'm trying to make a single line to check if a single element in Python list fits the criteria, but my current code will keep the loop going even if it hits a "True" -mark and thus only the last element counts for the check:
if [[CheckStatus(value, outsidevalue)] for value in valuelist] is True:
magic
(CheckStatus returns either True or False for every single value compared to outsidevalue and is supposed to accept is as true if a single value returns True)

that will always be false:
if [[CheckStatus(value, outsidevalue)] for value in valuelist] is True:
because you're comparing a list with a boolean.
What you want is any:
if any(CheckStatus(value, outsidevalue) for value in valuelist):
any iterates on the generator comprehension, calling your function on all elements until True is found (note that the inside square brackets have been removed, and we don't need to create a list comprehension, just a generator comprehension, which is faster)

Related

Check if all elements of list are prime in Raku

my #g = (1,2,3,4);
say reduce {is-prime}, #g; # ==> gives error
say reduce {is-prime *}, #g; #==> gives error
say reduce {is-prime}, (1,2,3,4); # ==> gives error
say so is-prime #g.all; # ==> gives error
How to check if all elements of list are prime in Raku?
The answers above are all helpful, but they fail to explain why your solution does not work. Basically reduce is not going to apply a function (in your case, is-prime) to every member of a list. You want map for that. The error says
Calling is-prime() will never work with signature of the proto ($, *%)
Because reduce expects an infix, thus binary, function, or a function with two arguments; what it does is to apply them to the first pair of elements, then to the result and the third element, and so on. Last statement does not work for a similar reason: you are calling is-prime with a list argument, not a single argument.
You're basically asking: are there any elements in this list which are not prime? I would write that as:
say "not all prime" if #g.first: !*.is-prime;
Please note though, that apparently 1 is not considered prime according to the is-prime function:
say 1.is-prime; # False
so the first would trigger on the 1 in your example, not on the 4.
There are of course may ways to do this. A very explicit way is using a for loop:
for #g -> $g {
if $g.is-prime {
say $g;
}
}
Or with a grep (you could leave the $_ implicit):
#g.grep({ $_.is-prime }).say
Both above are assuming you really want to filter the primes out. Of course you can also really check each number and get a boolean:
#g.map({ .is-prime }).say
There is a big problem with this:
say reduce {is-prime}, #g;
You created a lambda:
{ }
The only thing it does is calls a function:
is-prime
You didn't give the function any arguments though.
Is it just supposed to guess what the arguments should be?
If you meant to pass in is-prime as a reference, you should have used &is-prime rather than {is-prime}.
Of course that still wouldn't have worked.
The other problem is that reduce operates by recursively combining values.
It can't do that if it operates on one argument at a time.
The bare block lambda {}, takes zero or one argument, not two or more.
reduce is often combined with map.
It happens so often that there is a Wikipedia page about MapReduce.
say ( map &is-prime, #g ==> reduce { $^a and $^b } );
# False
say ( map &is-prime, 2,3,5 ==> reduce { $^a and $^b } );
# True
I wrote it that way so that map would be in the line before reduce, but perhaps it would be more clear this way:
say reduce {$^a and $^b}, map &is-prime, 2,3,5;
# True
reduce with an infix operator is so common that there is a shorter way to write it.
say [and] map &is-prime, 2,3,5;
# True
Of course it would be better to just find the first value that isn't prime, and say the inverse.
Since if there is even a single value that isn't prime that would mean they can't all be primes.
You have to be careful though, as you may think something like this would always work:
not #g.first: !*.is-prime;
It does happen to work for the values you gave it, but may not always.
first returns Nil if it can't find the value.
not (2,3,5).first: !*.is-prime;
# not Nil === True
not (2,3,4).first: !*.is-prime;
# not 4 === False
not (2,3,0,4).first: !*.is-prime;
# not 0 === True
That last one returned 0 which when combined with not returns True.
You could fix this with defined.
not defined (2,3,0,4).first: !*.is-prime;
# False
This only works if first wouldn't return an undefined element that happens to be in the list.
(Int,Any).first: Real
# Int
defined (Int,Any).first: Real
# False
You could fix that by asking for the index instead of the value.
You of course still need defined.
(Int,Any).first: :k, Real
# 0
defined (Int,Any).first: :k, Real
# True
The other way to fix it is to just use grep.
not (2,3,0,4).grep: !*.is-prime;
# not (0,4) === False
Since grep always returns a List, you don't have to worry about checking for 0 or undefined elements.
(A List is True if it contains any elements, no matter what the values.)
grep is smart enough to know that if you coerce to Bool that it can stop upon finding the first value.
So it short-circuits the same as if you had used first.
This results in some fairly funky code, with those two negating operators. So it should be put into a function.
sub all-prime ( +#_ ) {
# return False if we find any non-prime
not #_.grep: !*.is-prime
# grep short-circuits in Bool context, so this will stop early
}
This could still fail if you give it something weird
all-prime 2,3,5, Date.today;
# ERROR: No such method 'is-prime' for invocant of type 'Date'
If you care, add some error handling.
sub all-prime ( +#_ ) {
# return Nil if there was an error
CATCH { default { return Nil }}
# return False if we find any non-prime
not #_.grep: !*.is-prime
}
all-prime 2,3,5, Date.today;
# Nil
use the all junction:
say so all #g».is-prime; # False

Removes braces from variable

I am comparing two list:
gp_yu = set(agencys_sp2).intersection(gp_list_t)
the output is in braces like this {900}. What can i do to remove the braces
You can obtain an element from an iterable iterable (a set is an iterable, but lists, dictionaries, etc. are iterables as well) with:
element = next(iter(iterable))
In case the iterable contains two or more elements, it will return the first element (a set has no really a "first" element in the sense that the order can very over time, but it will return an element).
In case the iterable contains no elements at all (an empty set, list, tuple, dictionary, etc.), then it will raise a StopIteration error. You can however let the expression return a default value with:
element = next(iter(iterable), default)
So in case iterable contains one or more elements, the "first" element is returned, in case it is empty, it will return default.
Probably you mean some like how to get your set as a string, so just use join function.
Some like this ', '.join(gp_yu).
Check this topic for more information:
Python: how to join entries in a set into one string?

Want to skip number while performing for loop

While using for loop in python whatever range we initially define that is fixed.
In any case can we skip at some step like.code give i={0,1,2,3,4,5,6,7,8,9)
I want
i={0,1,2,3,4,8,9}
for i in range(0,10):
print i
if(i==4):
i=i+3
you can use list and in the loop check the list.
listinfo = [0,1,2,3,4,8,9]
for i in range(0,10):
if i in listinfo:
#do your stuff
The reason your code doesn't work is that every iteration of the for-loop begins by setting the value of i to the next item in the range, meaning that it doesn't matter how you set i during the loop's body.
Instead, you can have the loop body only execute for certain values like this:
for i in range(10):
if i not in range(5, 8):
print(i)

returning to a loop when it doesn't meet a certain condition

So I have a while loop that calculates the value of a variable for me.
If that variable does not reach the condition that I want to, is it possible to return to the while loop and insert new variables, and keep returning to the loop until I get the condition that i want.
balance=3329
annualInterestRate=0.2/12
month=0
min_pay=10
while month<12:
new_bal=balance+(balance*annualInterestRate)-min_pay
balance=new_bal
month=month+1
if balance>0:
min_pay+=10
So if by the end of the loop the balance>0 then I want to add 10 to min_pay and go through the loop with the original values. And I want it to keep going until balance<=0
Yes, you can use a nested while loop:
min_pay=10
while True:
balance=3329
annualInterestRate=0.2/12
month=0
while month<12:
new_bal=balance+(balance*annualInterestRate)-min_pay
balance=new_bal
month=month+1
if balance>0:
min_pay+=10
else:
break

Django OR query

How would I do:
FinancialStatements.objects.get(statement_id=statement_id)
or SalesStatements.objects.get(statement_id=statement_id)
The result will always yield one result.
I ended up using the try/except route here:
try:
statement_object = FinancialStatements.objects.get(statement_id=statement_id)
except FinancialStatements.DoesNotExist:
statement_object = SalesStatements.objects.get(statement_id=statement_id)
Why not simply do:
result = (FinancialStatements.objects.filter(statement_id=statement_id) or
SalesStatements.objects.filter(statement_id=statement_id))
This should work, because filter returns a list - and an empty list if no entries match. An empty list evaluates to false in python's boolean logic, e.g. try running:
print [] or "hello"
(Just as a check, compare print ["Hi"] or "hello")
So, if the first query returns empty, the second will then be run. However, if the first matches anything, this will be result and the second query will be ignored.
Addendum: result will then be of a list type - you'll need to extract the (one and only) element with result[0].