Kotlin toBoolean for numbers - kotlin

The following code produces false regardless of whether I have 0 or 1 as an input.
fun main() {
val num: String = readln().toString()
val b: Boolean = num.toBoolean()
println(b)
}
I wanted to convert 0 to false and 1 to true.

In Kotlin, numbers are not associated to booleans like in other languages. The convention 0=false and 1=true is not really present in the language or stdlib, so it's unlikely you'll find anything that does it out of the box.
If you really do want to support this case, you'll have to implement it yourself. One way to do it is like this:
fun main() {
val num = readln()
val b = num.zeroOrOneToBoolean()
println(b)
}
private fun String.zeroOrOneToBoolean(): Boolean = when(num) {
"0" -> false
"1" -> true
else -> throw IllegalArgumentException("$this cannot be converted to boolean, expected 0 or 1")
}
You could also choose to consider other things as true or false:
private fun String.toBooleanLenient(): Boolean = when(num) {
"0", "false", "False" -> false
"1", "true", "True" -> true
else -> throw IllegalArgumentException("$this cannot be converted to boolean")
}
Or you could decide that you want anything that is not "1" to be false, in which case you can really simply just use ==:
fun main() {
val num = readln()
val b = num == "1" // true for the string "1", false for everything else
println(b)
}

Related

Kotlin to filter certain options using When

How can I use When in Kotlin to do something if not in some certain conditions? for example
when(condition : String){
//not "A","B","C" -> return
// else -> continue to do something
}
I've tried some keyword or operator such as ! or not, but doesn't
work
For the specific case in your question, here are two ways I would do it:
when (myString) {
!in arrayOf("A", "B", "C") -> return
else -> {
// continue to do something
}
}
Just flipping the condition (swap the order of your code):
when (myString) {
"A", "B", "C" -> {
// continue to do something
}
else -> { }
}
if not in some certain conditions?
Exactly that.
let's suppose you have this :
val value = 5
to check if something is within a certain range of values:
when (value in 0..5) {
true -> {}
else -> {}
}
alternatively:
when (value !in 0..5) {
true -> {}
else -> {}
}
but making use of negative logic is sometimes harder to read or follow, so the first approach would probably be easier to understand perhaps.
similary for strings:
val range = arrayListOf("a", "b", "c")
when (value in range) {
true -> {}
else -> {}
}
you could also expand this further:
val value = "hello"
val allowedRange = arrayListOf("a", "b", "c")
val excludedRange = arrayListOf("x", "y", "z")
when (value) {
in allowedRange -> {
}
in excludedRange -> {
}
else -> {}
}

Can i check if condition is true for all elements in a list on Kotlin?

How can i check in if statement that condition is true for elements in a collection
fun main() {
var control = 20
val list = mutableListOf<Int>()
for (i in 1..20)
list.add(i)
while (true) {
control++
if (control % list[0] == 0 && control % list[1] == 0)
}
}
i only write 2 conditions for convenience
Not sure if you want to check if the condition is true for ALL the elements, or you just want to know which ONE in particular is true, or if ANY are true.
In the first scenario, where we want to know if ALL of them
val list = (1..20).toList() //a bit easier to create the list this way
val result = list.all { control % it == 0 }
println(result) //will print true if all of the elements are true, and false if at least one is false
The second scenario we can do a simple .map, to know each one individually.
val list = (1..20).toList()
val result = list.map { control % it == 0 }
println(result) //will print a list of type (true, false, true, etc) depending on each element
And if we want to check if ANY are true, we can do:
val list = (1..20).toList()
val result = list.any { control % it == 0 }
println(result) //will print true if any of the elements are true, and false if all of the elements are false
Edit since Todd mentioned none in the comments, I'll add a few other similar functions in case it would help others with similar questions.
Firstly, we don't actually need a list, all of these funcitons can work on the range directly (the ones above and the ones below)
val result = (1..20).all { it % 2 == 0 }
Other similar functions:
none - the opposite of all.
filter - will keep all elements for which the predicate is true.
filterNot - will keep all elements for which the predicate is false.
For example you can use filter:
fun main() {
val list = mutableListOf<Int>()
for (i in 1..20)
list.add(i)
list.filter { it % 2 === 1 }
.forEach { println(it) }
}
Change my code to this if anyone interested
fun main() {
var count = 20
var flag = false
val list = (1..20).toList()
while (true){
count++
if (list.all { count % it == 0 }){
println(count)
break
}
}
}

Check if a string contains only letters

How I can make a function that take a string and return the result whether the string contain alphabet letter only or not.
function all returns true if all characters match the given predicate.
fun String.onlyLetters() = all { it.isLetter() }
if (str.onlyLetters()) {
// only letters
}
else {
}
You can use the function firstOrNull() to search for the 1st non letter char and compare the result with null:
fun onlyLetters(s: String): Boolean = (s.firstOrNull { !it.isLetter() } == null)
or as an extension function:
fun String.onlyLetters(): Boolean = (firstOrNull { !it.isLetter() } == null)
Note that this way you will get true even if the string is empty.
If you don't want this then you should add another condition for the length like:
fun String.onlyLetters(): Boolean = length > 0 && (firstOrNull { !it.isLetter() } == null)
You could use a simple regular expression to validate the input:
fun isOnlyLetters(word: String): Boolean {
val regex = "^[A-Za-z]*$".toRegex()
return regex.matches(word)}
Alternatively,
making the regex ^[A-Za-z ]*$ (space after "z")would allow any amount of whitespace (such as in a phrase) at any point in the string (i.e. and still return true).
making the regex ^[A-Za-z ]+$ (* -> +) would return false for an empty string(i.e. ensure that there is at least one character in the input, be it a letter or space).
create an extension function isLettersOnly()
/*
* This fuction return true only if the string contain a-z or A-Z,
* Otherwise false*/
fun String.isLettersOnly(): Boolean {
val len = this.length
for (i in 0 until len) {
if (!this[i].isLetter()) {
return false
}
}
return true
}
1.check a string value
fun main() {
val text = "name"
if (text.isLettersOnly()) {
println("This is contain a-z,A-Z only")
} else {
println("This contain something else")
}
}
output:
This is contain a-z,A-Z only
2.check a string value
fun main() {
val text = "name 5"
if (text.isLettersOnly()) {
println("This is contain a-z,A-Z only")
} else {
println("This contain something else")
}
}
output:
This contain something else

Does the Kotlin "when" expression support compound boolean expression when using a subject?

Is it possible to provide a compound boolean expression in the when(subject) { ... } block?
The following will not compile
val num: Any = 2
when(num) {
/* compound boolean expression that uses implicit subject expression
* and an independent expression */
is Number && true -> println("TRUE")
else -> println("FALSE")
}
The following will compile, but results in FALSE. Is this the expected behavior?
val num: Any = 2
when(num) {
num is Number && true -> println("TRUE")
else -> println("FALSE")
}
I have a long list of when conditions and most of them only use the implicit subject but a couple need secondary conditions
//First case
//Prints TRUE if the num value is numeric and true.Anything else prints FALSE
val num: Any = 2
when {
num is Number && true -> println("TRUE")
else -> println("FALSE")
}
//Second case
//Prints true if the value is numeric OR true.Anything else prints FALSE
val num: Any = 2
when(num){
is Number , true -> println("TRUE")
else -> println("FALSE")
}
Is it possible to provide multiple boolean conditions when using a when(subject) { ... } expression?
Yes, you can separate multiple when conditions using a , (comma).
For instance, the following whens have the exact same behavior. Runnable playground demo here.
fun withoutComma(arg: Any?): String {
return when(arg) {
is String -> "FOO!" // returned when arg is an instance of String
true -> "bar!" // returned when arg == true
is Long -> "FOO!" // returned when arg is an instance of Long
false -> "bar!" // returned when arg == false
null -> "FOO!" // returned when arg == null
is Int -> "bar!" // returned when arg is an instance of Int
else -> "else!"
}
}
fun withComma(arg: Any?): String {
return when(arg) {
is String, is Long, null -> "FOO!" // returned when arg is an instance of String, or when arg is an instance of Long, or when arg == null
true, false, is Int -> "bar!" // returned when arg == true, or when arg == false, or when arg is an instance of Int
else -> "else!"
}
}
fun main() {
listOf("s", true, 999L, false, null, 123, emptyList<Any>()).forEach {
println("$it -> withoutComma: ${withoutComma(it)}")
println("$it -> withComma: ${withComma(it)}")
}
}
// Prints:
// s -> withoutComma: FOO!
// s -> withComma: FOO!
// true -> withoutComma: bar!
// true -> withComma: bar!
// 999 -> withoutComma: FOO!
// 999 -> withComma: FOO!
// false -> withoutComma: bar!
// false -> withComma: bar!
// null -> withoutComma: FOO!
// null -> withComma: FOO!
// 123 -> withoutComma: bar!
// 123 -> withComma: bar!
// [] -> withoutComma: else!
// [] -> withComma: else!
Regarding the first one: looking at the when grammar it is intended. Only in and is (and their negative counterparts) are allowed directly. Otherwise you only have expressions.
Now regarding your second one it may help to transform it to an if/else-statement first. Basically your when will look as follows then:
if (num == ((num is Number) && true)) println("TRUE")
else println("FALSE")
If looking at this it becomes clear why it always prints FALSE. While num is Number becomes true and true && true is still true, the num == true is false as num isn't even a boolean ;-)
Or in other words: your "subject" in the when is compared against each of the conditions (thanks Bwvolleyball for the comment).
What however I don't really understand (but that could also be my misunderstanding of the grammar)... looking at the grammar it seems as if the following would be possible:
when {
is Number -> TODO()
}
but as one could expect: it doesn't... but the last statement is rather a side-note.
If you want to have multiple conditions for the when statement to evaluate, you can also create a new variable and check all your cases when assigning it a value. It’s not always the best case if you’re working on a very large app and have to be conscious about memory, but it makes your code much more readable and concise
ex:
/*
Num is evaluated for whether it is greater than, less than, or equal to 0
and the corresponding String value is assigned to isNumberPositiveNegativeOrZero.
*/
val isNumberPositiveNegativeOrZero: String = when {
num > 0 -> “number is positive”
num < 0 -> “number is negative”
else -> “number is zero”
}
This can, of course, be expanded into however many cases you want to check.
(This is my first time answering a question on here so please excuse any accidents)

Kotlin closure to solve logical and operation

i want to create a closure where it take all the Boolean expression and methods, gives the final result
something like this
myAnd{
23<34
false
someFunction() //returns true
}
so the answer will be false
The solution i came with is this
fun myAnd(vararg flags: Boolean) = flags.all { it }
myAnd(true , false ,someFunction())
but this solution won't give the power of short circuiting while using and operator
Using blocks to implement short-circuiting and
fun someFunction() = true
fun and(vararg parameters: ()->Boolean): Boolean {
return parameters.all { it() }
}
fun main(args: Array<String>) {
and (
{23<34},
{false},
::someFunction
)
}
This works by passing in each predicate as a block, which means that they can be evaluated one by one, and if any of them returns false then all will return false immediately, short-circuiting the rest of them.
I can think of a quick solution that enables the following use:
val boolResult: Boolean = myAnd {
+ (23 < 34)
+ false
+ someFunction() //returns true
}
Here's the relevant code:
fun myAnd(bb: BooleanBuilder.() -> Unit) = BooleanBuilder().apply { bb() }.result
class BooleanBuilder {
var bools = listOf<Boolean>()
operator fun Boolean.unaryPlus() {
bools += this
}
fun result() = bools.all { it }
}
Explanation: It's a lightweight example of a custom DSL. The interesting part of this is BooleanBuilder.() -> Unit, a function literal with receiver, so that I can pass a lambda that's in the scope of a BooleanBuilder (lambda's receiver). This is necessary to use the member extension Boolean.unaryPlus that again enables the use of + boolean as shown.