I'm looking for a way to beautifully extract 'user id' from string in Groovy. Lets say I have string "key::${userId}" For example:
String s = "key::123456"
I can extract userId in java style as following
Long.parseLong(s.substring(s.indexOf("::") + 2))
But I believe that there is a way to make it shorter and more neatly
If key:: is always the prefix, you can use the - operator, combined with the as keyword for the String to long conversion:
String s = 'key::123456'
long userId = (s - 'key::') as long
You can use multiple assignment operator combined with tokenize method:
def (_,userId) = "key::123456".tokenize("::")
assert userId == "123456"
Related
I need to replace all content after a specific character in groovy with the value of a parameter,
my string is :
env.APP_VERSION="1.9"
And I would like to replace everything after the = sign with the value of a certain parameter let's call it $PARAM.
I was able to trim everything after the = sign,
but not replace it...
result = result.substring(0, result.indexOf('APP_VERSION='));
any help would be appreciated.
One of possible solutions is, indeed, to use regex. It should include:
(?<==) - A positive lookbehind for =.
.* - Match all chars (up to the end).
So the script can look like below:
src = 'env.APP_VERSION="1.9"'
PARAM = '"xyz"'
res = src.replaceFirst(/(?<==).*/, PARAM)
Another solution is to split the string on = and "mount" the result string
from:
The first string from split result.
= char.
Your replacement string.
This time the processing part of the script should be:
spl = src.split('=')
res = spl[0] + '=' + PARAM
Without knowing about your original intentions you have 2 options:
1) Do not reinvent the wheel and use GString magic:
String ver = '1.9'
String result = "env.APP_VERSION=\"$ver\""
2) use some regex:
result = result.replaceFirst( /APP_VERSION="[^"]+"/, 'APP_VERSION="something"' )
Is there any way to convert string like 'Dziękuję' to 'Dziekuje' or 'šećer' to 'secer' in kotlin. I have tried using java.text.Normalizer but it doesn't seem to work the desired way.
Normalizer only does half the work. Here's how you could use it:
private val REGEX_UNACCENT = "\\p{InCombiningDiacriticalMarks}+".toRegex()
fun CharSequence.unaccent(): String {
val temp = Normalizer.normalize(this, Normalizer.Form.NFD)
return REGEX_UNACCENT.replace(temp, "")
}
assert("áéíóů".unaccent() == "aeiou")
And here's how it works:
We are calling the normalize(). If we pass à, the method returns a + ` . Then using a regular expression, we clean up the string to keep only valid US-ASCII characters.
Source: http://www.rgagnon.com/javadetails/java-0456.html
Note that Normalizer is a Java class; this is not pure Kotlin and it will only work on JVM.
TL;DR:
Use Normalizer to canonically decomposed the Unicode thext.
Remove non-spacing combining characters (\p{Mn}).
fun String.removeNonSpacingMarks() =
Normalizer.normalize(this, Normalizer.Form.NFD)
.replace("\\p{Mn}+".toRegex(), "")
Long answer:
Using Normalizer you can transform the original text into an equivalent composed or decomposed form.
NFD: Canonical decomposition.
NFC: Canonical decomposition, followed by canonical composition.
.
(more info about normalization can be found in the Unicode® Standard Annex #15)
In our case, we are interested in NFD normalization form because it allows us to separate all the combined characters from the base character.
After decomposing the text, we have to run a regex to remove all the new characters resulting from the decomposition that correspond to combined characters.
Combined characters are special characters intended to be positioned relative to an associated base character. The Unicode Standard distinguishes two types of combining characters: spacing and nonspacing.
We are only interested in non-spacing combining characters. Diacritics are the principal class (but not the only one) of this group used with Latin, Greek, and Cyrillic scripts and their relatives.
To remove non-spacing characters with a regex we have to use \p{Mn}. This group includes all the 1,826 non-spacing characters.
Other answers uses \p{InCombiningDiacriticalMarks}, this block only includes combining diacritical marks. It is a subset of \p{Mn} that includes only 112 characters.
This is an extension function you can use and extend further:
fun String.normalize(): String {
val original = arrayOf("ę", "š")
val normalized = arrayOf("e", "s")
return this.map { it ->
val index = original.indexOf(it.toString())
if (index >= 0) normalized[index] else it
}.joinToString("")
}
Use it like this:
val originalText = "aębšc"
val normalizedText = originalText.normalize()
println(normalizedText)
will print
aebsc
Extend the arrays original and normalized with as many elements as you need.
In case anyone is strugling to do this in kotlin, this code works like a charm.
To avoid inconsistencies I also use .toUpperCase and Trim(). then i cast this function:
fun stripAccents(s: String):String{
if (s == null) {
return "";
}
val chars: CharArray = s.toCharArray()
var sb = StringBuilder(s)
var cont: Int = 0
while (chars.size > cont) {
var c: kotlin.Char
c = chars[cont]
var c2:String = c.toString()
//these are my needs, in case you need to convert other accents just Add new entries aqui
c2 = c2.replace("Ã", "A")
c2 = c2.replace("Õ", "O")
c2 = c2.replace("Ç", "C")
c2 = c2.replace("Á", "A")
c2 = c2.replace("Ó", "O")
c2 = c2.replace("Ê", "E")
c2 = c2.replace("É", "E")
c2 = c2.replace("Ú", "U")
c = c2.single()
sb.setCharAt(cont, c)
cont++
}
return sb.toString()
}
to use these fun cast the code like this:
var str: String
str = editText.text.toString() //get the text from EditText
str = str.toUpperCase().trim()
str = stripAccents(str) //call the function
Any idea how i can separate a string with character and numbers, for example
12345ABC678 to make it look like this
1|2|3|4|5|A|B|C|6|7|8??
Or if this is not possile, how can i take this string a put every character or nr of it in a different textBox like this?
You can use String.Join and String.ToCharArray:
string input = "12345ABC678";
string result = String.Join("|", input.ToCharArray());
Instead of ToCharArray(creates a new array) you could also cast the string to IEnumerable<char> to force it to use the right overload of String.Join:
string result = String.Join("|", (IEnumerable<char>)input);
use
String aString = "AaBbCcDd";
var chars = aString.ToCharArray();
Then you can loop over the array (chars)
So I am learning Kotlin now, and I was trying to do a calculator where if we can give expression like 4+3 or 3*5 and we will get the answer so I was trying to split that input string and then find what operator is used and what are the operands.
var list = str.split("+","-","*","/" )
so how can i get the delimiter that is used to split that string too.
I'm afraid that split method doesn't have this feature. You would have to split the the string via separate split calls. And compare the outcome with original string. If the string wasn't split by given delimiter that outcome should be the same.
Eg. like this:
var str = "5+1"
var delimiters = arrayOf("+","-","*","/")
var found = "Not found"
for (delimiter in delimiters) {
var splited = str.split(delimiter)
if(splited[0] != str) {
found = delimiter
break
}
}
println(found)
I have a Groovy method that currently works but is real ugly/hacky looking:
def parseId(String str) {
System.out.println("str: " + str)
int index = href.indexOf("repositoryId")
System.out.println("index: " + index)
int repoIndex = index + 13
System.out.println("repoIndex" + repoIndex)
String repoId = href.substring(repoIndex)
System.out.println("repoId is: " + repoId)
}
When this runs, you might get output like:
str: wsodk3oke30d30kdl4kof94j93jr94f3kd03k043k?planKey=si23j383&repositoryId=31850514
index: 59
repoIndex: 72
repoId is: 31850514
As you can see, I'm simply interested in obtaining the repositoryId value (everything after the = operator) out of the String. Is there a more efficient/Groovier way of doing this or this the only way?
There are a lot of ways to achieve what you want. I'll suggest a simple one using split:
sub = { it.split("repositoryId=")[1] }
str='wsodk3oke30d30kdl4kof94j93jr94f3kd03k043k?planKey=si23j383&repositoryId=31850514'
assert sub(str) == '31850514'
Using a regular expression you could do
def repositoryId = (str =~ "repositoryId=(.*)")[0][1]
The =~ is a regex matcher
or a shortcut regexp - if you are looking only for single match:
String repoId = str.replaceFirst( /.*&repositoryId=(\w+).*/, '$1' )
All the answers here contains regular expressions, however there are a bunch of string methods in Groovy.
String Function
Sample
Description
contains
myStringVar.contains(substring)
Returns true if and only if this string contains the specified sequence of char values
equals
myStringVar.equals(substring)
This is similar to the above but has to be an exact match for the check to return a true value
endsWith
myStringVar.endsWith(suffix)
This method checks the new value contains an ending string
startsWith
myStringVar.startsWith(prefix)
This method checks the new value contains an starting string
equalsIgnoreCase
myStringVar.equalsIgnoreCase(substring)
The same as equals but without case sensitivity
isEmpty
myStringVar.isEmpty()
Checks if myStringVar is populated or not.
matches
myStringVar.matches(substring)
This is the same as equals with the slight difference being that matches takes a regular string as a parameter unlike equals which takes another String object
replace
myStringVar.replace(old,new)
Returns a string resulting from replacing all occurrences of oldChar in this string with newChar
replaceAll
myStringVar.replaceAll(old_regex,new)
Replaces each substring of this string that matches the given regular expression with the given replacement
split
myStringVar.split(regex)
Splits this string around matches of the given regular expression
Source