Python if test condition fails when used with or - python-3.x

Greetings python experts. I had written an if condition as follows that fails to be false for objects that should be false. I am writing in python 3.8.5. Note instance_list in this example contains a list of resources that are in various states. I only want to append vm_instance_list with resources that are not in a TERMINATED or TERMINATING state.
instance_results = compute_client.list_instances(
compartment_id = compartment_id).data
vm_instance_list = []
for instance in instance_results:
if instance.lifecycle_state != "TERMINATED" or instance.lifecycle_state != "TERMINATING:
vm_instance_list.append(instance)
The above code appends vm_instance_list with every object in the list instance_results, aka each condition is interpreted as True for objects that are in a TERMINATED or TERMINATING lifecycle state. I have had to re-write to nest the if conditions, which works.
for instance in instance_results:
if instance.lifecycle_state != "TERMINATED:
if instance.lifecycle_state != "TERMINATING":
vm_instance_list.append(instance)
I have no idea what why I have had to nest the above if statements and would appreciate if anyone could share some insights.
Thanks so much,
Hank

In your first version, the result is ALWAYS true, so every item is appended.
Your second version is only true if both tests are true.
If you want the first version to behave like the second version, you need an 'and' statement, not an 'or'.

Let's trace through your first if statement in the case when instance.lifecycle_state is equal to "TERMINATED". The condition is as follows:
instance.lifecycle_state != "TERMINATED" or instance.lifecycle_state != "TERMINATING"
We can see that the first part of this statement is false (since lifecycle_state DOES equal "TERMINATED". The second part is true because lifecycle_state indeed does NOT equal "TERMINATING". So this whole expression simplifies to:
False or True
which finally simplifies (by the rules of or) to be just: True. So now we have seen why the body of the if is executed in the first case.
If we do a similar process in your second code snippet, we will see that the first condition is False (since lifecycle_state DOES equal "TERMINATED". So in this case the second condition is not checked, and the body of the if does not execute.
In fact, the second snippet is equivalent to the following condition:
instance.lifecycle_state != "TERMINATED" and instance.lifecycle_state != "TERMINATING"
Note that this is very similar to your original snippet, however we've replaced or with and. In fact, two nested if statements like this are equivalent to a single condition where both parts are joined by and.
By DeMorgan's Laws, this condition is also equivalent to:
not (instance.lifecycle_state == "TERMINATED" or instance.lifecycle_state == "TERMINATING")
which you may find clearer to understand.

Related

Kotlin and String.contains() not working as I thought

I thought I knew how string.contains() worked in Kotlin and Java, but apparently I don't.
I'vet got a small piece of code that takes a list of file names, and puts them in another list if the do not contain certain words.
for (i in 0..filliste.size-1) {
if (!filliste[i].contains("utenfastbopel") || !filliste.contains("sperret") ||
!filliste.contains("reservert")){
var a = filliste[i]
tempFnrliste += filliste[i].split("_")[0]
}
}
However, this does not exclude a file which contains the phrase "sperretstrengtreservert", even though both "reservert" and "sperret" is in the "not contains".
How come? I thought .contains found every occurence of a substring?
But if you look at the debug run, a file containing two of the phrases that are to be ignored, is indeed not ignored:
UPDATE:
To be clear, I'm looking for any of the file names to contain one OR more of the strings. So the logical OR/|| is correct.
However, I missed some indices. But adding them changed nothing. See the updated code below:
As far as I can see, the code now clearly says IF THE STRING DOES NOT CONTAIN THIS, THIS OR THIS SUBSTRING... But still, a string containing two of the substrings gets a match.
Strangely, if I only use ONE substring in the "not-contains" - for instance "reservert", the code does indeed skip all strings not containing that. But when I use the || operator for several substrings, things gets messed up.
"sperretstrengtreservert" does not contain utenfastbopel.
You are using || aka OR. Your first condition is true.
If any of these is true, it will go to the body of the condition.
!filliste[i].contains("utenfastbopel") ||
!filliste.contains("sperret") ||
!filliste.contains("reservert")
Also as said you are not accessing the same object in the follow-up conditions although it wouldn't change the result as is.
You need to change it from "at least one of these conditions must be true" to "all of these conditions must be true" && aka AND.
for (i in 0..filliste.size-1) {
val f = filliste[i]
if (!f.contains("utenfastbopel") && !f.contains("sperret") && !f.contains("reservert")) {
tempFnrliste += f.split("_")[0]
}
}

Not able to use for loop in ternary operator in arangodb

How do we write conditions in arango, that includes for loops. I can elaborate the requirement below.
My requirement is if a particular attribute(array type) exists in the arango collection, i would read data from the collection(that requires a loop) or else, might do the following :
return null
return empty string ""
do nothing.
Is this possible to achieve in arango?
The helping methods could be -->
-- has(collectionname, attributename)
-- The ternary operator ?:
let attribute1 = has(doc,"attribute1") ?(
for name in doc.attribute1.names
filter name.language == "xyz"
return name.name
) : ""
But this dosent work. Seems like arango compiler first attempts to compile the for loop, finds nulls and reports error as below. Instead, it should have compiled "has" function first for the ternary operator being used.
collection or array expected as operand to FOR loop; you provided a value of type 'null' (while executing)
If there is a better way of doing it, would appreciate the advice!!
Thanks in advance!
Nilotpal
Fakhrany here from ArangoDB.
Regarding your question, this is a known limitation.
From https://www.arangodb.com/docs/3.8/aql/fundamentals-limitations.html:
The following other limitations are known for AQL queries:
Subqueries that are used inside expressions are pulled out of these
expressions and executed beforehand. That means that subqueries do not
participate in lazy evaluation of operands, for example in the ternary
operator. Also see evaluation of subqueries.
Also noted here for the ternary operator:
https://www.arangodb.com/docs/3.8/aql/operators.html#ternary-operator.
An answer to the question what to do may be to use a FILTER before enumerating over the attributes:
FOR doc IN collection
/* the following filter will only let those documents passed in which "attribute1.names" is an array */
FILTER IS_ARRAY(doc.attribute1.names)
FOR name IN doc.attribute1.names
FILTER name.language == "xyz"
RETURN name.name
Other solutions are also possible. Depends a bit on the use case.

Spark: How to skip second condition in OR construction

When I try to check OR condition in Spark where function, the second condition is executed even thought first condition is true.
How can I skip the check of second condition?
df.
...
.where(
(
lit(lastLoadingDate).isNull
.or(
col(srcDTTM) > lastLoadingDate.format(formatterDTTM)
)
)
&& col(SrcDTTM) <= currentLoadingDate.format(formatterDTTM)
)
I tried even check next expression:
df.
...
.where(
(
lit(true)
.or(
col(srcDTTM) > lastLoadingDate.format(formatterDTTM)
)
)
&& col(SrcDTTM) <= currentLoadingDate.format(formatterDTTM)
)
But second condition:
col(srcDTTM) > lastLoadingDate.format(formatterDTTM)
is always executed.
Skip the check of second condition may result in incomplete data, because it is or judgment. If the second condition is true and the first condition is false, the amount of data in the result set will increase.
Checking the second condition in OR judgement wont make any difference when the first condition is true. Assume adding another condition or using any other function to skip the second condition check. If first check is false then condition to check if first one is true or false and then going to the second part of OR judgement. It will be like 3 conditions instead of 2. Its better to use OR judgement as it is.

how to use ternary operator in mustache template

I have a scenario where I am getting {{isdone}} value with Boolean data.
I want to be printed as "pending" for false value and "Done" for true.
I'm using below code, Which isn't working.
{{isdone}} == false ? "pending" : "Done"
Use the ^ block for else.
You can (now) use the ^ block for an else or false condition. Something like this should work:
{{#isdone}}Done{{/isdone}}{{^isdone}}pending{{/isdone}}
Or as a more readable multi-line block of code:
{{#isdone}}
Done
{{/isdone}}
{{^isdone}}
pending
{{/isdone}}
As long as you have control of your context data, correct way is to pass another variable, that will already contain pending or Done beforehand.
If you don't have control over the data, then maybe moustache isn't good for you as you may need template engine that can have some more logic in it to transform data a bit.
You might want to register a ternary helper for that
Handlebars.registerHelper("ternary", function (condition, trueValue, falseValue, options) {
return condition ? trueValue : falseValue;
});
and then in your templates use it like
{{ternary isdone "Done" "pending"}}

Groovy - How can I compare part of a list to a string

I have a list which contains two types of text. One type is used for authorization while other type is used for all other purposes.
The type used for authorization always uses the same text + some code after it.
I would like to compare content of these two types of text and separate them based on content.
My idea is to look for pattern in authorization type and if it matches the pattern then this would be marked as authorization, otherwise it would be marked as "other".
I researched about comparison of patterns in Groovy, but all variations I tried did not work for me. Here is the part which should do the comparison, I am obviously doing something wrong but I don't know what.
jdbcOperations.queryForList(sql).collect { row ->
if(assert (row['MSG'] ==~ /token/)){
mark as authorization
}
else{
mark as other
}
}
Sorry for the vague code, I can not share more than this.
I think you just missing the match for the rest of the text, since you are looking only for the first part to match.
assert ("abc" ==~ /abc/) == true
assert ("abcdefg" ==~ /abc/) == false
assert ("abcdefg" ==~ /abc(.*)/) == true // <--- This can also be made more complicated

Resources