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
Related
Error :
Kotlin: Type mismatch: inferred type is String but Unit was expected
code :
fun main() {
val a = 2
var data: String = if (a != 2) {
return "Hello"
} else {
return "World"
}
}
Your code should be like this
var data: String = if (a != 2) {
"Hello"
} else {
"World"
}
By using return you are returning from the main function which has the return type set to "Unit". If you want to display the text, you should then call println(data).
Fun fact, when used like this you can even ignore the "{}" and make it one line like this :
var data: String = if (a != 2) "Hello" else "World"
I have a very large list of numbers. I need to pass this list of numbers as a URL query parameter. Since these lists can get so large, it could potentially cause the request URL to exceed the allowed length of a URL; also, it's a bit difficult to debug a string of sequential numbers (E.G. 1,2,3,..,500,782). To remedy these issues, I would like to convert the sequential number list string to one that is formatted using a range notation (E.G. -5..-3,1..500,782). How do I create this range notation string using Kotlin and how do I parse the string back to a collection of numbers also using Kotlin?
This will convert a Collection<Int> to a string that uses the "range notation" specified:
fun Collection<Int>.toRangesString(): String {
if (this.isEmpty()) {
return ""
}
if (this.size <= 2) {
return this.toSortedSet().joinToString(",")
}
val rangeStrings = mutableListOf<String>()
var start: Int? = null
var prev: Int? = null
for (num in this.toSortedSet()) {
if (prev == null) {
start = num
prev = num
continue
}
if (num != (prev + 1)) {
_addRangeString(rangeStrings, start!!, prev)
start = num
prev = num
continue
}
prev = num
}
if (start != null) {
_addRangeString(rangeStrings, start, prev!!)
}
return rangeStrings.joinToString(",")
}
private fun _addRangeString(rangeStrings: MutableList<String>, start: Int, prev: Int) {
rangeStrings.add(
when {
(start == prev) -> start.toString()
((start + 1) == prev) -> "${start},${prev}"
else -> "${start}..${prev}"
}
)
}
...and this will parse those range notated strings into a Set<Int>:
fun parseRangesString(str: String): Set<Int> {
if (str.isBlank()) {
return setOf()
}
val ranges = str.trim().split(",")
val numbers = mutableListOf<Int>()
for (range in ranges) {
if (range.contains("..")) {
val (start, end) = range.split("..")
numbers.addAll(start.toInt()..end.toInt())
continue
}
numbers.add(range.toInt())
}
return numbers.toSet()
}
...and, finally, even better than using a huge collection of numbers, you can use Kotlin's IntRange (or LongRange) class:
fun toIntRanges(str: String): Collection<IntRange> = _toRanges(str, ::_createIntRange)
fun toLongRanges(str: String): Collection<LongRange> = _toRanges(str, ::_createLongRange)
private fun <T : ClosedRange<*>> _toRanges(str: String, createRange: (start: String, end: String) -> T): Collection<T> {
if (str.isBlank()) {
return listOf()
}
val rangeStrs = str.trim().split(",")
val ranges = mutableListOf<T>()
for (rangeStr in rangeStrs) {
if (rangeStr.contains("..")) {
val (start, end) = rangeStr.split("..")
ranges.add(createRange(start, end))
continue
}
ranges.add(createRange(rangeStr, rangeStr))
}
return ranges.toList()
}
private fun _createIntRange(start: String, end: String) = IntRange(start.toInt(), end.toInt())
private fun _createLongRange(start: String, end: String) = LongRange(start.toLong(), end.toLong())
for all the examples on the internet i cant figure out when and how is kotlins let ran?
if(phones.size == 0){
phones.add("")
}
return phones[0]
so if phones list size is 0, we add empty string and return that instead.
Now how would one do same with let ?
phones.let {
return ""
}
does this work with size 0, or do i have to have null list?
do i need return keyword, if yes, where?
is the above fun always going to return empty string? or just when phones is null?
when is this let code block even ran?
Update:
val cakes = listOf("carrot", "cheese", "chocolate")
fun main(args: Array<String>) {
var cakesEaten = 0
while (cakesEaten < 3) { // 1
cakesEaten ++
val result = cakes?.let{
if(cakesEaten == 2) {
"HeyLo"
} else {
2
}
}
println("result value = $result")
when(result) {
is String -> println(" result variable is a String")
is Int -> println(" result variable is Integer")
}
}
}
result value = 2
result variable is Integer
result value = HeyLo
result variable is a String
result value = 2
result variable is Integer
Original post
If your 'phones' Object is a Nullable type,
val result = phones?.let{
// this block runs only if phones object is not null
// items can be accessed like it.size
// expression result will be returned. no need to mention return.
if(it.size == 0) {
it.add("")
it[0]
} else it.size
}
result value will be either it[0] or it.size and its type will be Any.
But if this the functionality you need you can check Markos solution.
If you're interested in how to write your logic in Kotlin's FP idiom, it doesn't involve let at all:
phones.takeIf { it.isEmpty() }?.add("")
return phones[0]
However, I don't find this idiom better than what you started out with.
I am working on a console application in Kotlin where I accept multiple arguments in main() function
fun main(args: Array<String>) {
// validation & String to Integer conversion
}
I want to check whether the String is a valid integer and convert the same or else I have to throw some exception.
How can I resolve this?
You could call toInt() on your String instances:
fun main(args: Array<String>) {
for (str in args) {
try {
val parsedInt = str.toInt()
println("The parsed int is $parsedInt")
} catch (nfe: NumberFormatException) {
// not a valid int
}
}
}
Or toIntOrNull() as an alternative:
for (str in args) {
val parsedInt = str.toIntOrNull()
if (parsedInt != null) {
println("The parsed int is $parsedInt")
} else {
// not a valid int
}
}
If you don't care about the invalid values, then you could combine toIntOrNull() with the safe call operator and a scope function, for example:
for (str in args) {
str.toIntOrNull()?.let {
println("The parsed int is $it")
}
}
Actually, there are several ways:
Given:
// aString is the string that we want to convert to number
// defaultValue is the backup value (integer) we'll have in case of conversion failed
var aString: String = "aString"
var defaultValue : Int = defaultValue
Then we have:
Operation
Successful operation
Unsuccessful Operation
aString.toInt()
Numeric value
NumberFormatException
aString.toIntOrNull()
Numeric value
null
aString.toIntOrNull() ?: defaultValue
Numeric value
defaultValue
If aString is a valid integer, then we will get is numeric value, else, based on the function used, see a result in column Unsuccessful Operation.
val i = "42".toIntOrNull()
Keep in mind that the result is nullable as the name suggests.
As suggested above, use toIntOrNull().
Parses the string as an [Int] number and returns the result
or null if the string is not a valid representation of a number.
val a = "11".toIntOrNull() // 11
val b = "-11".toIntOrNull() // -11
val c = "11.7".toIntOrNull() // null
val d = "11.0".toIntOrNull() // null
val e = "abc".toIntOrNull() // null
val f = null?.toIntOrNull() // null
I use this util function:
fun safeInt(text: String, fallback: Int): Int {
return text.toIntOrNull() ?: fallback
}
In Kotlin:
Simply do that
val abc = try {stringNumber.toInt()}catch (e:Exception){0}
In catch block you can set default value for any case string is not converted to "Int".
string_name.toString().toInt()
converts string_name to String and then the resulting String is converted to int.
i would go with something like this.
import java.util.*
fun String?.asOptionalInt() = Optional.ofNullable(this).map { it.toIntOrNull() }
fun main(args: Array<String>) {
val intArgs = args.map {
it.asOptionalInt().orElseThrow {
IllegalArgumentException("cannot parse to int $it")
}
}
println(intArgs)
}
this is quite a nice way to do this, without introducing unsafe nullable values.
add (?) before fun toInt()
val number_int = str?.toInt()
You can Direct Change by using readLine()!!.toInt()
Example:
fun main(){
print("Enter the radius = ")
var r1 = readLine()!!.toInt()
var area = (3.14*r1*r1)
println("Area is $area")
}
fun getIntValueFromString(value : String): Int {
var returnValue = ""
value.forEach {
val item = it.toString().toIntOrNull()
if(item is Int){
returnValue += item.toString()
}
}
return returnValue.toInt()
}
I was trying to port a Swift script to Kotlin but it's not working as expected, what the code does is to consume a string while the condition is true (need it for a parser). In Swift it works as expected but in Kotlin it doesn't (I just started with Kotlin a month ago so maybe I'm missing something).
Swift
extension String {
#discardableResult public mutating func consumeWhile(test: (String) -> Bool) -> String {
var chars = [Character](self.characters)
var result = ""
while chars.count > 0 && test(String(chars[0])) {
result.append(chars.remove(at: 0))
}
self = String(chars)
return result
}
}
Kotlin
fun String.consumeWhile(test: (String) -> Boolean): String {
if (isEmpty()) return ""
val chars = toCharArray().toMutableList()
var result = ""
var i = -1
while (chars.isNotEmpty() && test(chars.first().toString())) {
result += chars.removeAt(0)
++i
}
removeRange(0..i)
return result
}
So the basic usage will look like
val myString = "--Test" // IntelliJ suggests change var to val
val consumedString = myString.consumeWhile{ it != "-" }
println("result: $myString consumedString: $consumedString")
// expected: "result: Test consumedString: --"
// but got: "result: --Test consumedString: --"
Edit: Thanks for all the answers, don't know if will be possible to do like I want because as mentioned string are immutable in Kotlin/Java (just using the same string).
I forgot to mention that I need the consumed string, basically b/c I'm doing a parser so I need to store the consumed chars and the mutated string. I will leave open this question but I ended up creating a class that implements only a few String class methods.
class Line(var string: String) {
val length: Int
get() = string.length
fun consumeWhile(test: (String) -> Boolean): String {
if (string.isEmpty()) return ""
val chars = string.toCharArray().toMutableList()
var result = ""
while (chars.isNotEmpty() && test(chars.first().toString())) {
result += chars.removeAt(0)
}
string = chars.joinToString("")
return result
}
fun isNullOrEmpty(): Boolean {
return string.isNullOrEmpty()
}
fun isNotEmpty(): Boolean {
return string.isNotEmpty()
}
private fun removeRange(range: IntRange) {
string = string.removeRange(range)
}
operator fun get(i: Int): Char {
return string[i]
}
}
Usage example
val line = Line(string)
if (line.isNotEmpty() && line[0].toString() == "(") {
line.consumeWhile { it == "(" }
while (line.isNotEmpty() && line[0].toString() != ")") {
line.consumeWhile { it == " " }
val key = line.consumeWhile { it != "=" }
line.consumeWhile { it == "\"" || it == "=" }
val value = line.consumeWhile { it != "\"" }
line.consumeWhile { it == "\"" }
attributes[key] = value
}
line.consumeWhile { it == ")" }
}
String is immutable in Kotlin & Java, so you can't modify its state anyway.
You should avoiding to makes the wheels repeatedly, there is an existing function String#dropWhile(Char) in Kotlin. one thing you need to do is invert the condition, for example:
val result = "--Test".dropWhile { it == '-' }
// ^--- "Test"
In both Java and Kotlin String is immutable and you cannot change it after it has been created.
In swift this presumably can be turned off through the mutating modifier. However in Kotlin removeRange(0..i) creates a new String object which you then discard.
To have it behave as you want you will need to either:
Create a wrapper object that contains a string that can be replaced.
Return both the split string and the rest as a Pair, you can then use the destructuring operators to assign it as [_, myString] = myString.consumeWhile {}
Kotlin Strings are immutable and cannot be modified in place. Instead you can create a new String and return it
fun String.consumeWhile(test: (String) -> Boolean): String {
if (isEmpty()) return ""
val chars = toCharArray().toMutableList()
while (chars.isNotEmpty() && test(chars.first().toString())) {
chars.removeAt(0)
// Do something with the char
}
return chars.joinToString(separator = "")
}
Additionally, unless I am misunderstanding, your test condition should be it == "-" to get the result you want:
val myString = "--Test"
val newString = myString.consumeWhile{ it == "-" }
println("result: $newString")
You use
myString.consumeWhile{ it != "-" }
which stops consuming as soon as it meets the first "-", and thus it's nothing more to do.
The code works as it should, if you use
myString.consumeWhile{ it == "-" }
you will get the expected output as is correct.
I ended up creating a class that implements only a few String class methods.
class Line(var string: String) {
val length: Int
get() = string.length
fun consumeWhile(test: (String) -> Boolean): String {
if (string.isEmpty()) return ""
val chars = string.toCharArray().toMutableList()
var result = ""
while (chars.isNotEmpty() && test(chars.first().toString())) {
result += chars.removeAt(0)
}
string = chars.joinToString("")
return result
}
fun isNullOrEmpty(): Boolean {
return string.isNullOrEmpty()
}
fun isNotEmpty(): Boolean {
return string.isNotEmpty()
}
private fun removeRange(range: IntRange) {
string = string.removeRange(range)
}
operator fun get(i: Int): Char {
return string[i]
}
}
Usage example
val line = Line(string)
if (line.isNotEmpty() && line[0].toString() == "(") {
line.consumeWhile { it == "(" }
while (line.isNotEmpty() && line[0].toString() != ")") {
line.consumeWhile { it == " " }
val key = line.consumeWhile { it != "=" }
line.consumeWhile { it == "\"" || it == "=" }
val value = line.consumeWhile { it != "\"" }
line.consumeWhile { it == "\"" }
attributes[key] = value
}
line.consumeWhile { it == ")" }
}
Obs: for now will mark as answered, till a better solution comes out