How to copy one string's n number of characters to another string in Kotlin? - kotlin

Let's take a string var str = "Hello Kotlin". I want to copy first 5 character of str to another variable strHello. I was wondering is there any function of doing this or I have to apply a loop and copy characters one by one.

As Tim commented, there's a substring() method which does exactly this, so you can simply do:
val strHello = str.substring(0, 5)
(The first parameter is the 0-based index of the first character to take; and the second is the index of the character to stop before.)
There are many, many methods available on most of the common types.  If you're using an IDE such as IDEA or Eclipse, you should see a list of them pop up after you type str..  (That's one of many good reasons for using an IDE.)  Or check the official documentation.

Please use the string.take(n) utility.
More details at
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/take.html
I was using substring in my project, but it gave an exception when the length of the string was smaller than the second index of substring.
val name1 = "This is a very very long name"
// To copy to another string
val name2 = name1.take(5)
println(name1.substring(0..5))
println(name1.substring(0..50)) // Gives EXCEPTION
println(name1.take(5))
println(name1.take(50)) // No EXCEPTION

Related

Kotlin input first and last name with a twist

Seems a pretty simple program, but I can't figure out what I'm doing wrong. Any help is greatly appreciated!
TASK Write a program that reads the first name and the last name of a person, each on a separate line. Then, print the first letter of the first name with a dot and then the last name (with a single space in between): for example, Arthur Dent would be A. Dent
I've tried the following code:
fun main() {
val s1 = readLine()
val s2 = readLine()
println(s1.first() +"." + " " + s2)
}
Which returns an error: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
This is pretty straightforward in Python, but been struggling to solve it in Kotlin.
Thanks in advance!
Looking at the readLine docs it states that:
Return the line read or null if the input stream is redirected to a file and the end of file has been reached. (also if you fake an end file indication)
This means that both s1 and s2 are nullable. You would have seen this if you would have explicitly declared the type of the vals (something that beginners in kotlin should probably always do), as they would have been String?.
So, if we want to get the first letter (or do more or less anything), we need to use the ? safe call to avoid a NPE. The reason you don't get any error with s2 is because the default invocation of .toString will just return a String with the value of null.
Now even if you do add the safe call you will still get an error, that being that you can't concatenate null to a String. And you can simply solve it by using template instead of concatenation (which is actually the prefered way in kotlin). So we will have this:
println("${s1?.first()}. $s2")
Some changes due to the single input requirement. If you only have one input of type John Doe then the above code won't work, because you are reading 2 separate lines, one of which does not exist, making the lastName null. Doing is for a single input needs a bit more work:
val line = readLine()?.split(" ")
val firstNameInitial = line?.getOrNull(0)?.first()
val lastName = line?.getOrNull(1)
println("$firstNameInitial. $lastName")
This assumes that there are no people with a space in their names (not sure if true or not),that nobody will enter a middle name, and that the first and last name are separated by a " " space.
As per Joffrey's comment, we can also use the elvis operator to ensure that the readLine is not null, by throwing our own exception stating that the input is not readable.
val line = (readLine() ?: error("Unexpected end of input, expected first and last name in format \"John Doe\"")).split(" ")
val firstNameInitial = line.getOrNull(0)?.first() // in case we receive an empty string
val lastName = line.getOrNull(1) //in case we only receive one name
println("$firstNameInitial. $lastName")

Java - Index a String (Substring)

I have this string:
201057&channelTitle=null_JS
I want to be able to cut out the '201057' and make it a new variable. But I don't always know how long the digits will be, so can I somehow use the '&' as a reference?\
myDigits substring(0, position of &)?
Thanks
Sure, you can split the string along the &.
String s = "201057&channelTitle=null_JS";
String[] parts = s.split("&");
String newVar = parts[0];
The expected result here is
parts[0] = "201057";
parts[1] = "channelTitle=null_JS";
In production code you chould check of course the length of the parts array, in case no "&" was present.
Several programming languages also support the useful inverse operation
String s2 = parts.join("&"); // should have same value like s
Alas this one is not part of the Java standard libs, but e.g. Apache Commons Lang features it.
Always read the API first. There is an indexOf method in String that will return you the first index of the character/String you gave it.
You can use myDigits.substring(0, myDigits.indexOf('&');
However, if you want to get all of the arguments in the query separately, then you should use mvw's answer.

What do numbers in braces e.g. "{0}" mean?

I've been looking around but having great difficulty finding the answer to this question as the thing I'm looking for is so unspecific.
I've seen a lot of code which uses {0} in it, and I still can't work out what it's doing. Here's an example:
Dim literal As String = "CatDogFence"
Dim substring As String = literal.Substring(6)
Console.WriteLine("Substring: {0}", substring)
Console.WriteLine("Substring: {0}", substring)
Is the same as
Console.WriteLine("Substring: " & substring)
When using Console.WriteLine, {n} will insert the nth argument into the string, then write it.
A more complex example can be seen here:
Console.WriteLine("{0} {1}{2}", "Stack", "Over", "flow")
It will print Stack Overflow.
Console.WriteLine() and String.Format() use that syntax.
It allows you to inject a variable into a string, for example:
dim name = "james"
String.Format("Hello {0}", name)
That string will be "Hello james"
Using Console.Writeline:
Console.WriteLine("Hello {0}",name)
That will write "Hello james"
It's a placeholder. Beginning at the second parameter (substring in your case), they are included in the given string in the given order. This way you avoid long string concatenations using + operator and can do easier language localization, because you can pull the compete string including the placeholders to some external resource file etc.
It is called composite formatting and is supported by many methods, Console.WriteLine being one. Besides indexed placeholders there are other features available. Here is a link to the documentation that shows some of the other features of composite formatting.
Composite Formatting

Weird results when splitting strings in VB.NET

I was getting weird results when doing multiple splits on a string, so I decided to make a simple test to figure out what was going on
testString "1234567891011121314151617181920"
If I wanted to get whats between 10 to 20 in Javascript I would do this:
var results = testString.split("10")[1].split("20")[0]
Which would return 111213141516171819
However when I do this in VB I get 111
Split(testString,"10")(1).Split("20")(0)
It seems the 2nd split is only recognizing the first character no matter what I put.
So it's stopping when it finds the next "2" in the string, even "2abc" would have the same outcome even though that string doesn't even exist.
String.Split does not have an overload that takes only a String. The argument is a Char array or String array. Your string is probably being converted to a char array. Explicitly pass a string array like so:
testString.Split(New String() { "10" }, StringSplitOptions.None)
Try wrapping the second split so it's fashioned like the first one, i.e.:
Split( Split(testString,"10")(1), "20" )(0)"
Vb treats the delimiter argument only as a single character.
This is a tricky scenario that I have seen trip people up before, so I think it is worth a little more explanation than the other answers give. In your original format Split(testString,"10")(1).Split("20")(0), you are unknowingly using two DIFFERENT Split functions.
The first Split(testString,"10") is using the Microsoft.VisualBasic.Strings.Split function, which takes String type parameters. http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.strings.split(v=vs.110).aspx
The second .Split("20")(0) is using System.String.Split method, which does not have an overload that takes a String parameter. http://msdn.microsoft.com/en-us/library/System.String.Split(v=vs.110).aspx
So what was happening is:
Split(testString,"10") uses Microsoft.VisualBasic.Strings.Split, which
returns new String() {"123456789", "11121314151617181920"}
(1) means get 1st position of the returned array, which is "11121314151617181920"
"11121314151617181920".Split("20")(0) uses System.String.Split, and attempts to split on string separator "20"
NOTE: The string "20" param gets implicitly converted to a char "2" because the only single parameter overload of String.Split has a signature of Public Function Split (ParamArray separator As Char()) As String(). The ParamArray parameter option allows you to pass a comma delimited list of values into the function, similar to how String.Format works with a dynamic # of replacement values. http://msdn.microsoft.com/en-us/library/538f81ec.aspx
Step 3 code becomes "11121314151617181920".Split(new Char() {CChar("20")})(0), which using literal values is "11121314151617181920".Split(new Char() {"2"c})(0). The result is {"111", "13141516171819", "0"}. Get the 0th position, returns "111".
So to avoid confusion, you should convert your code to use the same version of Split on both sides.
Either of the 2 examples below should work:
Example 1: Using Microsoft.VisualBasic.Strings.Split:
Split( Split(testString,"10")(1), "20" )(0)
Example 2: Using System.String.Split:
testString _
.Split(New String() {"10"}, StringSplitOptions.None)(1) _
.Split(New String() {"20"}, StringSplitOptions.None)(0)

lua variable in pattern match

Im just wondering if it is possible to put a variable in a pattern match in Lua. Like something similar to the following:
var = "hello"
pattern = string.match(datasource, "(var)%s(a%+)")
The reason I need to do this is because the variable "var" will change periodically. (it will be in a loop)
Cheers in advance
Lua doesn't handle string interpolation inside of the quotes. Instead, you'll need to concatenate the parts with the var as a var reference and the rest as quote strings.
"("..var..")%s(a%+)" starts with a "(" as a string literal, concatenates the variable, then finishes off the rest of the string with a string literal.
Use "("..var..")%s(a%+)" instead.
I needed the same thing I think, a variable in a pattern match, but the above solution didn't work for me. I'm posting my solution in case it helps someone, didn't find anything else on the net like it.
I read a ': ' delimited file (name: tel) and want to search by name in the file and have the name and telephone number as answer.
local FileToSearch = h:read'*a' -- Read all the file
var = io.read() -- ask the name
string.gmatch(FileToSearch, ''..var..': '..'%d+') -- search for name, concatenate with number