Specific regex in Kotlin - kotlin

I created two functions .One checkUnit to get the unit from string and second whatU if input contains m u n p T g k to convert the input value .But there is some mismatch .
My pattern examples:
"m(O|h|F|s|H|A|V)" -this is for the m before unit this part needs improve
\b0-9.Ohm.(?<![0-9])\b" - this is for Ohm this part is wrong
val pattern = Regex(whatToFind)
val result = pattern.containsMatchIn(whatToFind)
This is for all invalid characters in input [A-EI-LNP-SUW-Za-gi-jloq-tw-zvV/ '$&+,{}:;=_\[]|`~?##"<>^*()%!-£€¥¢©®™¿÷¦¬×§¶°]
How to check if m is before Ohm and after number in string 100mOhm in regex Kotlin in more effective way ?

You can take a look at the Pattern documentation. There are several predefined character classes like \d+ for a digit. So you can use the following method:
boolean matched = Pattern.matches("\\d+mOhm", "100mOhm");
Or if you want to have the pattern for a longer time you can use the following method:
Pattern pattern = Pattern.compile("\\d+mOhm");
Matcher matcher = pattern.matcher("100mOhm");
boolean matched = matcher.matches();
If you want to use only Kotlin, you can use the following code:
val regex = "\\d+mOhm".toRegex()
val matched = regex.matches("100mOhm")
I found also a nice tutorial with more information about Koltin Regex.

This meets your requirement:
import java.util.Scanner
fun main() {
val scanner = Scanner(System.`in`)
val s = scanner.nextLine()
println("\\d+mOhm".toRegex().matches(s))
}
Perhaps you can modify it from here.

Related

Convert String into list of Pairs: Kotlin

Is there an easier approach to convert an Intellij IDEA environment variable into a list of Tuples?
My environment variable for Intellij is
GROCERY_LIST=[("egg", "dairy"),("chicken", "meat"),("apple", "fruit")]
The environment variable gets accessed into Kotlin file as String.
val g_list = System.getenv("GROCERY_LIST")
Ideally I'd like to iterate over g_list, first element being ("egg", "dairy") and so on.
And then ("egg", "dairy") is a tuple/pair
I have tried to split g_list by comma that's NOT inside quotes i.e
val splitted_list = g_list.split(",(?=(?:[^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*\$)".toRegex()).toTypedArray()
this gives me first element as [("egg", second element as "dairy")] and so on.
Also created a data class and tried to map the string into data class using jacksonObjectMapper following this link:
val mapper = jacksonObjectMapper()
val g_list = System.getenv("GROCERY_LIST")
val myList: List<Shopping> = mapper.readValue(g_list)
data class Shopping(val a: String, val b: String)
You can create a regular expression to match all strings in your environmental variable.
Regex::findAll()
Then loop through the strings while creating a list of Shopping objects.
// Raw data set.
val groceryList: String = "[(\"egg\", \"dairy\"),(\"chicken\", \"meat\"),(\"apple\", \"fruit\")]"
// Build regular expression.
val regex = Regex("\"([\\s\\S]+?)\"")
val matchResult = regex.findAll(groceryList)
val iterator = matchResult.iterator()
// Create a List of `Shopping` objects.
var first: String = "";
var second: String = "";
val shoppingList = mutableListOf<Shopping>()
var i = 0;
while (iterator.hasNext()) {
val value = iterator.next().value;
if (i % 2 == 0) {
first = value;
} else {
second = value;
shoppingList.add(Shopping(first, second))
first = ""
second = ""
}
i++
}
// Print Shopping List.
for (s in shoppingList) {
println(s)
}
// Output.
/*
Shopping(a="egg", b="dairy")
Shopping(a="chicken", b="meat")
Shopping(a="apple", b="fruit")
*/
data class Shopping(val a: String, val b: String)
Never a good idea to use regex to match parenthesis.
I would suggest a step-by-step approach:
You could first match the name and the value by
(\w+)=(.*)
There you get the name in group 1 and the value in group 2 without caring about any subsequent = characters that might appear in the value.
If you then want to split the value, I would get rid of start and end parenthesis first by matching by
(?<=\[\().*(?=\)\])
(or simply cut off the first and last two characters of the string, if it is always given it starts with [( and ends in )])
Then get the single list entries from splitting by
\),\(
(take care that the split operation also takes a regex, so you have to escape it)
And for each list entry you could split that simply by
,\s*
or, if you want the quote character to be removed, use a match with
\"(.*)\",\s*\"(.*)\"
where group 1 contains the key (left of equals sign) and group 2 the value (right of equals sign)

Split character from string in Idiomatic way Kotlin

Hey I am working in kotlin. I have one string in which I want to split into list from there where I should provide character. I'll explain in details
For example 1
val string = "Birth Control"
val searchText = "n"
Output
["Birth Co", "trol"]
For example 2
val string = "Bladder Infection"
val searchText = "i"
Actual Output
["Bladder ", "nfect", "on"]
Expect Output
["Bladder ", "nfection"]
I tried some code but example 1 is working fine but example 2 is not because I only want to split first occurrence.
val splitList = title?.split(searchText, ignoreCase = true)?.toMutableList()
splitList?.remove(searchText)
Can someone guide me how to solve this idiomatic way. Thanks
You miss the limit option of the split function. If you give it a value of 2 the result list will have a maximum of 2 entries:
val result = "Bladder Infection".split("i", ignoreCase = true, limit = 2)

how to search for series of strings in a sentence in kotlin

I have an ArrayList of items. Each item has long strings for example
("The cat is in the hat","It's warm outside","It's cold outside")
what I am trying to do is search for a series of strings for example "It's outside" in any given order in the ArrayList above and it should find 2 of them.
This is what I tried:
fun clickItem(criteria: String) {
productList = productListAll.filter {it: Data
it.title.contains(criteria, ignoreCase = true)
}
} as ArrayList<Data>
This works fine when the words I am looking for are in sequence. However, I am trying to get strings in any given order. Does anyone know how to accomplish that?
We can do this by splitting title and criteria by whitespaces to create a set of words. Then we use containsAll() to check if title contains all of words from criteria. Additionally, we need to convert both of them to lowercase (or uppercase), so the search will be case-insensitive:
private val whitespace = Regex("\\s+")
fun clickItem(criteria: String): List<Data> {
val criteriaWords = criteria.lowercase().split(whitespace).toSet()
return productListAll.filter {
it.title.lowercase().split(whitespace).containsAll(criteriaWords)
}
}
Note that searching through text is not that trivial, so simple solutions will be always limited. For example, we won't find "it's" when searching for "it is", etc.

Make string starts with specified prefix in Kotlin

I am trying to find out the native way to concatenate prefix to string, but only in case, it was not.
This code checks the text variable and makes it start with "#".
val text = "123456"
val prefix = "#"
val textFormatted = (if (text.startsWith(prefix)) "" else prefix ) + text
I hope there are clean solutions somewhere in Kotlin
An alternative would be to use removePrefix:
val textFormatted = prefix + text.removePrefix(prefix)
Otherwise you could also keep the if but write it the following way to avoid extra parentheses and extra concatenation, and also make the code closer to the semantics:
val textFormatted = if (text.startsWith(prefix)) text else "$prefix$text"
But your solution works too.
You can use the string interpolation from the kotlin, example:
val text:String = "123456#123456"
val prefix:String = "#"
val interpolation:String = "#${text.removePrefix(prefix)}"

Removing unncecessary parts from String

I'm consuming a client that I cannot change and it sends me data that looks like that:
"BOOKING - PAID (price.amount=70, price.currency=EUR)"
and I would like to retrieve from that only 70 EUR
What is the best way to do such thing in kotlin? I didn't find any removeAll("", "", ...) functions for String, only replace but would have to chain them to remove both price.amount and price.currency.
EDIT:
Need to get BOOKING - PAID (70 EUR) actually, forgot about that part.
Thinking about it and as you updated your question to really remove only a part from the string, here are some approaches for removing several strings from a given string:
Using regex:
input.replace("""(price\.(amount|currency)=|,)""".toRegex(), "")
Using a list of strings to remove:
sequenceOf(input, "price.amount=", ",", "price.currency=")
.reduce { acc, rm -> acc.replace(rm, "") }
// alternatively using var:
var input = TODO()
sequenceOf("price.amount=", ",", "price.currency=")
.forEach { input = input.replace(it, "") }
Still: most of the time I would rather take the other route: extracting the information you require and just print that, as also Baptiste has shown in his answer. Otherwise you may start to expose answers of that service you didn't want to expose in the first place.
This sounds like a job for regular expressions!
fun main(args: Array<String>) {
val str = "BOOKING - PAID (price.amount=70, price.currency=EUR)"
// The expressions between parentheses will map to groups[1], groups[2] and groups[3] respectively
val reg = Regex("""(.*) \(price\.amount=([0-9]+), price\.currency=([A-Z]+)\)""")
// Apply the regular expression on the string
val results = reg.find(str)
results?.groupValues?.let { groups ->
// If results and groupValues aren't null, we've got our values!
val type = groups[1]
val price = groups[2]
val currency = groups[3]
println("$type ($price $currency)") // BOOKING - PAID (70 EUR)
}
// Or as suggested by #Roland:
results?.destructured?.let { (type, price, currency) ->
println("$type ($price $currency)") // BOOKING - PAID (70 EUR)
}
}
Regular expressions allow you to take a string as entry, and find a pattern in it. They're quite used in all languages, you can find more info about them all over the place.
EDIT: edited for the updated question. I chose to treat "BOOKING - PAID" as a single string, but there's an infinite number of ways to do it, depending on your granularity needs; and honestly, at that point a regex might be a bit overkill. :)
Without regex by string manipulation and assuming that this is the pattern:
fun main(args: Array <String> ) {
val str = "BOOKING - PAID (price.amount=70, price.currency=EUR)"
val type = str.substringBefore("(").trim()
val price = str.substringBeforeLast(",").substringAfter("=")
val currency = str.substringAfterLast("=").substringBefore(")")
val result = "$type ($price $currency)"
println(result)
}
will print
BOOKING - PAID (70 EUR)
Edit: I use str.substringBeforeLast(",") to get the price, in case , could be used as a delimeter for decimal part in the number