Swift optional multiple tests in conditional - ios

I want to do something like this with an optional in swift.
var opt:MyOptional?
func myfunction() {
if (opt == nil) || (opt?.x != 10 && opt?.y != 20)) {
opt = MyOptional()
opt.x = 10
opt.y = 20
}
}
My question is if this is a valid pattern, even though it compiles and runs. Does Swift compiler ensures condition 2 runs after condition 1 (opt!= nil)?

Well && and || operators in swift are Left Associative which means your evaluation of conditions goes from left hand side.
(opt != nil). // result 1
this condition will get evaluate first and as you are using the || operator.
Secondaly your (opt?.x != 10 && opt2?.y != 20) // result 2
will get now evaluate if your result 1 is false otherwise it would have gone in the loop because of || operator
final condition
if (result 1 || result 2) {
if only result 1 is true it not evaluate for result 2 due to || operator otherwise it would calculate result 2 and if result 2 is true its a success

Assuming you have got a typo this code should looks like this:
struct MyOptional {
var x: Int = 0
var y: Int = 0
}
class SomeClass {
var opt: MyOptional?
func myFunction() {
if let unwrappedOpt = opt,
unwrappedOpt.x != 10 && unwrappedOpt.y != 20 {
opt = MyOptional(x: 10, y: 20)
}
}
}
What about your question? You are right.

Related

Why does my shunting yard implementation mix operator order?

I have been trying to implement the shunting yard algorithm, but the output of my parser is incorrect.
let mut stack: Vec<String> = vec![];
let mut op_stack: Vec<String> = vec![];
for current in sub_tree {
if current.tok_type == TokenType::NUMBER || current.tok_type == TokenType::NEGNUMBER {
self.parse();
stack.push(current.content.clone());
}
if current.tok_type == TokenType::SUBBIN
|| current.tok_type == TokenType::PLUSBIN
|| current.tok_type == TokenType::DIVBIN
|| current.tok_type == TokenType::MULBIN
{
while op_stack.len() > 0 && op_stack.last().unwrap().to_string() != "(" {
if op_prec(&op_stack.last().unwrap().to_string()) > op_prec(&current.content)
|| (op_prec(&op_stack.last().unwrap().to_string()) == op_prec(&current.content)
&& op_asso(&current.content) == "left")
{
stack.push(op_stack.pop().unwrap().to_string());
} else {
break;
}
}
op_stack.push(current.content.to_string())
}
}
The original equation I am parsing: 1 + 2 * 3
I expected the following output: 1 2 3 * +
Instead I get this: 1 2 3 + *
I think I am going wrong somewhere in my while loop but I don't really know. I tried to follow the example on the Wikipedia article.
I forgot I had to pop from the operator stack back into the output stack at the end.
Comparing your code
if current.tok_type == TokenType::SUBBIN
|| current.tok_type == TokenType::PLUSBIN
|| current.tok_type == TokenType::DIVBIN
|| current.tok_type == TokenType::MULBIN
{
while op_stack.len() > 0 && op_stack.last().unwrap().to_string() != "(" {
if op_prec(&op_stack.last().unwrap().to_string()) > op_prec(&current.content)
|| (op_prec(&op_stack.last().unwrap().to_string()) == op_prec(&current.content)
&& op_asso(&current.content) == "left")
{
stack.push(op_stack.pop().unwrap().to_string());
} else {
break;
}
}
op_stack.push(current.content.to_string())
}
with the Wikipedia code https://en.wikipedia.org/wiki/Shunting-yard_algorithm
- an operator o1:
while (
there is an operator o2 other than the left parenthesis at the top
of the operator stack, and (o2 has greater precedence than o1
or they have the same precedence and o1 is left-associative)
):
pop o2 from the operator stack into the output queue
push o1 onto the operator stack
It looks like they are functionally identical.
So I suspect the problem is not with the code, but instead with the precedence table. If you have the precedence of + and * the wrong way round, then you would get this behaviour. It is easy to get this mixed up as some source have precedence going from tighter binding to loser one and some have the opposite. Compare Wikipedia order of operations and Operator Precedence in Java, use the former.

How to use a Ternary Operator with multiple condition in flutter dart?

how to use ternary if else with two or more condition using "OR" and "AND" like
if(foo == 1 || foo == 2)
{
do something
}
{
else do something
}
i want to use it like
foo == 1 || foo == 2 ? doSomething : doSomething
If you're referring to else if statements in dart, then this ternary operator:
(foo==1)? something1():(foo==2)? something2(): something3();
is equivalent to this:
if(foo == 1){
something1();
}
elseif(foo == 2){
something2();
}
else something3();
For three conditions use:
value: (i == 1) ? 1 : (i == 2) ? 2 : 0
Try below
(2 > 3)?print("It is more than 3"):print("It is less than 3");
////Prints It is less than 3 to the console
For AND try this,
// here both or multiple conditions needs to satisfy
if (primaryImageUploaded == true && signatureImageUploaded == true) {
// status bool condition in true
} else {
// if false
}
For OR try this,
// here need ONLY any one condition to satisfy
if (primaryImageUploaded == true || signatureImageUploaded == true) {
// status bool condition in true
} else {
// if false
}
Another Dart Syntax
if (100 > 50) {
print("100 is greater than 50");
}
it is easy,
if(foo == 1 || foo == 2)
{
do something
}
{
else do something
}
it can be written thus for OR statement
foo==1 || foo==2 ? do something : else do something
it can be written thus for AND statement
foo==1 && foo==2 ? do something : else do something
both will work perfectly
EDITED
The original answer has run a little bit of from the question asked. Below is my edited answer.
To use ternary operator
(foo == 1 || foo == 2) ? doSomething() : doSomethingElse();
For my cleaner approach
{1, 2}.contains(foo) ? doSomething() : doSomethingElse();
ORIGINAL
The cleaner way for me is
if ({1, 2}.contains(foo)) {
//do something
} else {
//do something else
}
Here is an example of the same
Text((managerStatus == "pending")
? "Requested"
: (adminStatus == "confirm")
? "Amount credited"
: "Admin Pending")
Try this:
foo == 1 ? doSomething1 : (foo == 2 ? doSomething1 : doSomething2)
If you have to include multiple conditions then you should use parantheses
Simple Multiple check in one condition
if(in_array($foo, [1,2,'other'])) {
//do something
}
else {
//else do something
}
void main(){
var a,b,c,d;
a = 7;
b = 9;
c = 11;
d = 15;
print((a>b)?((a>c)?((a>d)?a:d):c):(b>c)?((b>d)?b:d):(c>d)?c:d);
}

Swift 2 Logical AND(&) Operator

I am new to programming and trying to find a simpler way to do this:
if state[0] != 0 && state[1] != 0 && state[2] != 0 && state[3] != 0 && state[4] != 0 && state[5] != 0 && state[6] != 0 && state[7] != 0 && state[8] != 0 {
gameOverLabel.text = "It's a tie."
gameOverLabel.hidden = false
active = false
}
I tried the code below but it reacted like a OR rather than a AND.
if state[0&1&2&3&4&5&6&7&8] != 0 {
gameOverLabel.text = "It's a tie."
gameOverLabel.hidden = false
active = false
}
Thanks for any help!
Assuming that your intention is to check if all array elements
are different from zero, the easiest approach would be
if !state.contains(0) { ... }
Your code
if state[0&1&2&3&4&5&6&7&8] != 0 { ... }
does not work
as intended because here the bitwise AND 0&1&2&3&4&5&6&7&8
is computed first (with result zero), so that is equivalent to
if state[0] != 0 { ... }
let state = [0,1,2,0,4,5,6,7]
if state.filter{$0 != 0}.count > 0 {
gameOverLabel.text = "It's a tie."
gameOverLabel.hidden = false
active = false
}
Try this one
The general case with an Array of indices
The short version
let indices = [4,2,9,6,5,3,8,0]
if !indices.contains({ state[$0] == 0 }) {
// ...
}
A second version which only shows the possibilities of Swift:
if !indices.lazy.map{ state[$0] }.contains(0) {
// ...
}
The lazy is used since otherwise map would apply the closure to all indices whereas lazy applies it on average only to half the elements (contains determines the number of executions of the closure).
Note: There is probably no performance improvement for a small amount of indices. The first version is certainly (ever so slightly) faster.
A specific range of indices
Just use the approach above with
let indices = 5...9
Or directly operate on the sub sequence of Array which is ArraySlice.
Side note: Even though it seems that ArraySlice (return type of Array[Range<Int>]) is a value type, internally it is a reference type (like Array) which only copies itself on mutation. In addition ArraySlice is only a view into the array (as long none of them is mutated). So it could be even faster than the first approach.
if !state[24...42].contains(0) {
// ...
}

Program doesn't work without an initial value

The program works fine with var dig = 0 and it doesn't work with var dig:Int I get an error: Variable "dig" used before being initialized Could you explain me why?
func myFunc(a:Int, b:Int) {
var c = a / b
var o = a % b
var v = 0
var dig = 0
if o != 0 {println("\(a)/\(b) = \(c) и \(o)/\(b)")}
else {println("\(a)/\(b) = \(c)")}
if a > b {
v = b
}
else {
v = a
}
for var i = 1; i <= v; ++i {
if a % i == 0 && b % i == 0 {dig = i}
}
println("\(dig) -  greatest common denominator of \(a) and \(b)")
}
myFunc(27,81)
The only place you set the value of dig is inside of an if statement that is inside of a for loop. The Swift compiler does not know if the body of the for loop will be executed, and it doesn't know if the if statement will ever be true, so it has to assume that there is a path in which dig is not initialized.
Consider this simpler example:
func myFunc(a:Int, b:Int) {
var dig: Int
if a >= b {
dig = 3
}
if a < b {
dig = 4
}
println("\(dig) - greatest common denominator of \(a) and \(b)")
}
This example also gives the same error, because Swift considers each if separately. It is obvious to us that a is either greater than or equal to b or it is less than b, but Swift doesn't go that far in evaluating the situation. It just considers that each if may not be true, and dig is only set inside of ifs, so it is possible (as far as Swift is concerned) that dig may not be set.
func myFunc(a:Int, b:Int) {
var dig: Int
if a >= b {
dig = 3
} else {
dig = 4
}
println("\(dig) - greatest common denominator of \(a) and \(b)")
}
If you change the second condition to an else, Swift is then happy because it can reason that the if must be true or false and dig is set in each path, so it will certainly have a value before the println statement.
The compiler does not know mathematics good enough to
recognize that the statement
if a % i == 0 && b % i == 0 {dig = i}
is actually executed at least once (for i == 1). Therefore
the compiler assumes that dig might be undefined at
println("\(dig) - greatest common denominator of \(a) and \(b)")
Assigning an initial value in
var dig = 0
is the correct solution.
Btw., the Euclidean Algorithm is a much more effective method to
compute the greatest common divisor, see for example
http://rosettacode.org/wiki/Greatest_common_divisor#Swift.

Filtering IQueryable result set using parameters

I'm getting confused with this and I know there will be a more slick way of starting it off. The 'result' variable has many records and I want to check if IN_SiteId is > 0 and filter on it, same after that for LandownerId and PaymentCategoryId etc. If I can get the right approach for the first 2 I will be ok from there. This should be easier but having a brick wall day. Any comments appreciated
public IQueryable rptRentPaidMonthly(int IN_SiteId, int IN_LandownerId, int IN_PaymentCategoryId, int IN_PaymentTypeId, string IN_ShowRelevantProportion)
{
var result = this._lmsDb.rptRentPaidMonthly(IN_daysFrom, IN_daysTo, IN_SiteId, IN_LandownerId, IN_PaymentCategoryId, IN_PaymentTypeId, IN_ShowRelevantProportion);
if (IN_SiteId > 0)
{
var searchResults = (from s in result
where (s.SiteId == #IN_SiteId)
select s);
return searchResults.AsQueryable();
}
return result.AsQueryable();
}
I'm not a LINQ expert but I think you can do something like this:
public IQueryable rptRentPaidMonthly(int IN_SiteId, int IN_LandownerId, int IN_PaymentCategoryId, int IN_PaymentTypeId, string IN_ShowRelevantProportion)
{
var result = this._lmsDb.rptRentPaidMonthly(IN_daysFrom, IN_daysTo, IN_SiteId, IN_LandownerId, IN_PaymentCategoryId, IN_PaymentTypeId, IN_ShowRelevantProportion);
var searchResults = (from s in result
where (IN_SiteId <= 0 || s.SiteId == IN_SiteId)
&& (IN_LandownerId <= 0 || s.LandownerId == IN_LandownerId)
&& (IN_PaymentCategoryId <= 0 || s.PaymentCategoryId == IN_PaymentCategoryId)
&& (IN_PaymentTypeId <= 0 || s.PaymentTypeId == In_PaymentTypeId)
select s);
return searchResults.AsQueryable();
}
The where clause checks if each filter value is less than or equal to 0, if so then it will return true and will not evaluate the next bit which attempts to filter the actual field on the value provided.

Resources