I am trying to compare multiple variables to an expression, like so:
if 1 <= x && x <= 5 &&
1 <= y && y <= 5 &&
1 <= z && z <= 5 {
// Code to run if true
}
I found a question related to comparing a variable to multiple specific values, which is not what I want because it is not a comparison in an inequality.
Is there any way I can shorten this, in any way?
For example making an inequality like 1 <= x && x <= 5 shortened, or making me able to compare x, y, and z easily in other ways?
Use ranges!
if (1...5).contains(x) &&
(1...5).contains(y) &&
(1...5).contains(z) {
}
Alternatively, create a closure that checks whether something is in range:
let inRange: (Int) -> Bool = (1...5).contains
if inRange(x) && inRange(y) && inRange(z) {
}
As Hamish has suggested, the allSatisfy method in Swift 4.2 can be implemented as an extension like this:
extension Sequence {
func allSatisfy(_ predicate: (Element) throws -> Bool) rethrows -> Bool {
return try !contains { try !predicate($0) }
}
}
Another option: match against a tuple of ranges:
if case (1...5, 1...5, 1...5) = (x, y, z) {
}
Or use a switch-statement to match against one or more
tuples of ranges:
switch (x, y, z) {
case (1...5, 1...5, 1...5):
print("all between 1 and 5")
case (..<0, ..<0, ..<0):
print("all negative")
default:
break
}
(Compare Can I use the range operator with if statement in Swift?.)
Maybe like this:
if [x,y,z].compactMap{ (1...5).contains($0) }.contains(true) {
//Do stuff
}
Related
In Dart, is there a simple way to check whether the sum of a list will produce a 'real' value (a value that doesn't overflow or underflow)?
Examples:
overflowSafeSum([0,1,2]) //3
overflowSafeSum([1,9223372036854775807]) //Over
overflowSafeSum([-1,-9223372036854775808]) //Under
I'm new to dart, this is the best I got right now:
import 'dart:math' show pow;
enum Overflow {
over,
under,
}
void main() {
//idea: Iterate through the elements of a list and add them,
//each time the sum overflows: increase overflowCounter by 1
//each time the sum underflows: decrease overflowCounter by 1
//if all the elements have been added and the overflowCounter == 0, the sum must be real
overflowSafeSum(List<int> userList) {
var sum = 0, overflowCounter = 0;
for (int index = 0, nextTerm;
index < userList.length;
index++, sum += nextTerm) {
nextTerm = userList[index];
if (sum.sign != nextTerm.sign) {
continue; //adding a postive and negative can't overflow or underflow
} else if (sum >= 0 && nextTerm >= 0) {
if ((sum + nextTerm) < 0) overflowCounter++;
} else {
if ((sum + nextTerm) >= 0) overflowCounter--;
}
}
if (overflowCounter == 0) {
return sum;
} else if (overflowCounter > 0) {
return Overflow.over;
} else {
return Overflow.under;
}
}
var myList = [1,0,(pow(2,63)-1).toInt()];
print(overflowSafeSum(myList)); //Overflow.over
}
(To be pedantic: "underflow" is not negative overflow. Overflow occurs when the magnitude of a number is too large to be represented, regardless of sign. Underflow is an issue with floating-point operations where the magnitude of a number is too small (too close to 0) to be represented.)
You can't generally detect overflow with Dart ints since Dart for the web is transpiled to JavaScript, where ints are backed by JavaScript numbers (IEEE-754 double-precision floating-point values). If you instead use Int32 or Int64 from package:fixnum (or if you restrict yourself to the Dart VM), then you could make a helper function like:
class OverflowException implements Exception {
OverflowException({this.positive = true});
bool positive;
}
Int64 checkedAdd(Int64 a, Int64 b) {
var sum = a + b;
if (a > 0 && b > 0 && sum < 0) {
throw OverflowException(positive: true);
}
if (a < 0 && b < 0 && sum > 0) {
throw OverflowException(positive: false);
}
return sum;
}
From there, you could trivially add a function that calls it in a loop:
Int64 overflowSafeSum(Iterable<int> numbers) {
var sum = Int64(0);
for (var number in numbers) {
sum = checkedAdd(sum, Int32(number));
}
return sum;
}
or if you prefer using Iterable.fold:
Int64 overflowSafeSum(Iterable<int> numbers) =>
numbers.fold<Int64>(Int64(0), (sum, i) => checkedAdd(sum, Int64(i)));
I have multiple variables which needs the same check in a if-statement in Dart. I need to know if there is at least one of the variables > 0.
For example:
var a = 1;
var b = 0;
var c = 0;
if ((a > 0) || (b > 0) || (c > 0)) {
print('Yeh!');
}
This should be done easier, like in Python.
The following code isn't valid, but I tried this:
if ((a || b || c) > 0) {
print('Yeh!');
}
Any tips would be nice.
One way would be to create a List and to use Iterable.any:
if ([a, b, c].any((x) => x > 0)) {
print('Yeh!');
}
For example, I have the following code which creates a Mono with a list of 3 numbers 1,2,3. I want to filter out the number 1. The result would be a list of 2 numbers 2,3. What should I do in the flatMapMany so that it skip the number 1?
Mono.just(new LinkedList<>{{
add(1);
add(2);
add(3);
}})
.flatMapMany(number -> {
if (number == 1) {
// not return
}
return number;
})
.collectList()
.map(numbers -> {
// numbers should be 2,3
})
A follow-up question
what if in my code I return Flux.empty() when number is 1
.flatMapMany(number -> {
if (number == 1) {
return Flux.empty()
}
return number;
})
.filter(i ->{
// how to filter out Flux.empty() ?
})
In the filter, how can I detect if i is empty flux and filter it out
Take a look at this example. You can use flatMapIterable to convert a mono of list to Flux.
Mono.just(List.of(1,2,3))
.flatMapIterable(Function.identity())
.filter(i -> i != 1)
.collectList()
.subscribe(s -> System.out.println(s)); //prints [2,3]
For the follow up question. We need to use .handle which is a combination of map and filter methods.
Flux.fromIterable(List.of(1, 2, 3))
.handle((number, sink) -> {
if (number != 1) {
sink.next(number);
}
})
.collectList()
.subscribe(s -> System.out.println(s));
If you really want to go with your approach, then we need to filter like this
Flux.fromIterable(List.of(1, 2, 3))
.flatMap((number) -> number == 1 ? Flux.empty() : Flux.just(number))
.collectList()
.subscribe(s -> System.out.println(s));
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.
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.