how to work with strings in Kotlin and string manipulation? - kotlin

fun main (args: Array<String>) {
val Myself = "Programmer"
var Alphi = Myself[5]
println(Alphi)
}
The above code works and outputs a.
How can I use the same logic to output "grammer" in Alphi variable?

The same you would do in Java:
val myself = "Programmer"
val alphi = myself.substring(3)

Related

Kotlin Creating List<List<Map<String, String>>>

I am trying to return List<List<Map<String, String>>> from a function in kotlin. I'm new to kotlin.
Edit1
Here's how I am attempting to to this
val a = mutableListOf(mutableListOf(mutableMapOf<String, String>()))
The problem with the above variable is, I am unable to figure out how to insert data into this variable. I tried with this:
val a = mutableListOf(mutableListOf(mutableMapOf<String, String>()))
val b = mutableListOf(mutableMapOf<String, String>())
val c = mutableMapOf<String, String>()
c.put("c", "n")
b.add(c)
a.add(b)
This is giving me:
[[{}], [{}, {c=n}]]
What I want is [[{c=n}]]
Can someone tell me how I can insert data into it?
The end goal I am trying to achieve is to store data in the form of List<List<Map<String, String>>>
EDIT 2
The function for which I am trying to write this dat structure:
fun processReport(file: Scanner): MutableList<List<Map<String, String>>> {
val result = mutableListOf<List<Map<String, String>>>()
val columnNames = file.nextLine().split(",")
while (file.hasNext()) {
val record = mutableListOf<Map<String, String>>()
val rowValues = file.nextLine()
.replace(",(?=[^\"]*\"[^\"]*(?:\"[^\"]*\"[^\"]*)*$)".toRegex(), "")
.split(",")
for (i in rowValues.indices) {
record.add(mapOf(columnNames[i] to rowValues[i]))
print(columnNames[i] + " : " + rowValues[i] + " ")
}
result.add(record)
}
return result
}
You don't need to use mutable data structures. You can define it like this:
fun main() {
val a = listOf(listOf(mapOf("c" to "n")))
println(a)
}
Output:
[[{c=n}]]
If you wanted to use mutable data structures and add the data later, you could do it like this:
fun main() {
val map = mutableMapOf<String, String>()
val innerList = mutableListOf<Map<String, String>>()
val outerList = mutableListOf<List<Map<String, String>>>()
map["c"] = "n"
innerList.add(map)
outerList.add(innerList)
println(outerList)
}
The output is the same, although the lists and maps are mutable.
In response to the 2nd edit. Ah, you're parsing a CSV. You shouldn't try to do that yourself, but you should use a library. Here's an example using Apache Commons CSV
fun processReport(file: File): List<List<Map<String, String>>> {
val parser = CSVParser.parse(file, Charset.defaultCharset(), CSVFormat.DEFAULT.withHeader())
return parser.records.map {
it.toMap().entries.map { (k, v) -> mapOf(k to v) }
}
}
For the following CSV:
foo,bar,baz
a,b,c
1,2,3
It produces:
[[{foo=a}, {bar=b}, {baz=c}], [{foo=1}, {bar=2}, {baz=3}]]
Note that you can simplify it further if you're happy returning a list of maps:
fun processReport(file: File): List<Map<String, String>> {
val parser = CSVParser.parse(file, Charset.defaultCharset(), CSVFormat.DEFAULT.withHeader())
return parser.records.map { it.toMap() }
}
Output:
[{foo=a, bar=b, baz=c}, {foo=1, bar=2, baz=3}]
I'm using Charset.defaultCharset() here, but you should change it to whatever character set the CSV is in.

how to replace duplicated string using re{n,} in Kotlin?

I want change "aaa" or "aa..." to "." using Regex(re{2,})
Below is my code
var answer = "aaa"
var re = Regex("re{2,}a") // Regex("are{2,}")
answer = re.replace(answer,".")
println(answer)
Regex("re{2,}a") and Regex("are{2,}")
Both println aaa
How can I replace duplicated string using re{n,} ??
fun main(args: Array<String>) {
var tests = arrayOf("a","aa","aaa","aaaa")
val re = Regex("a(a+)")
tests.forEach {t->
val result = re.replace(t,".")
println(result)
}
}
output:
a
.
.
.
Generic regex to replace any duplicates (not only duplicate a symbols) is (?<symbol>.)\k<symbol>+
You may define an extension function for convenient usage:
private val duplicateRegex = "(?<symbol>.)\\k<symbol>+".toRegex()
fun String.replaceDuplicatesWith(replacement: String): String = replace(duplicateRegex, replacement)
Usage:
println("a".replaceDuplicatesWith(".")) //a
println("aaa".replaceDuplicatesWith(".")) //.
println("aa...".replaceDuplicatesWith(".")) //..
If you want duplicates to be iteratively replaced (like "aa..." -> ".." -> ".") you'll need an auxilary recursive method:
tailrec fun String.iterativelyReplaceDuplicatesWith(replacement: String): String {
val result = this.replaceDuplicatesWith(replacement)
return if (result == this) result else result.iterativelyReplaceDuplicatesWith(replacement)
}
Usage:
println("a".iterativelyReplaceDuplicatesWith(".")) //a
println("aaa".iterativelyReplaceDuplicatesWith(".")) //.
println("aa...".iterativelyReplaceDuplicatesWith(".")) //.

How to declare mutableListOf of arrays?

I want to declare mutableListOf arrays but I don't know how. Google shows me examples like var mutableList1 = mutableListOf<Int>() and etc, but not arrays case(((
import java.util.*
fun main(args: Array<String>) {
var mutableList1 = mutableListOf<Arrays>()
var mutableList2 = mutableListOf(arrayOf<Int>()) //works, but it contains empty array:(
mutableList1.add(arrayOf(1,1)) //error
}
You can do it like this:
val list = mutableListOf<Array<Int>>()
list.add(arrayOf(1, 1))
Edit: As Animesh Sahu (thanks!) has pointed out in the comments, if you don't need boxed integers (no nulls in the arrays), you can use the primitive arrays instead and avoid their overhead:
val list = mutableListOf<IntArray>()
list.add(intArrayOf(1, 1))
You don't need to use mutableListOf
for example
val distributionList = mutableListOf<ParticipantDTO>()
participantVolumeList.forEach {
distributionList.add(
ParticipantDTO(
participantUuid = it.get(PARTICIPANT_VOLUMES.PARTICIPANT_UUID)
)
)
}
better rewrite to
val distributionList = participantVolumeList.map { mapToParticipant(it) }
private fun mapToParticipant(
participantVolumesRec: JParticipantRecord
): ParticipantDTO {
return ParticipantDTO().apply {
participantUuid = participantVolumesRec.get(PARTICIPANT_VOLUMES.PARTICIPANT_UUID)
}
}

Can I combine the builder pattern with a lambda expression?

The following lambda expression operates on a class which was created outside of the lambda.
I consider this clumsy. Is there a better way to this?
class Builder {
var searchTerms = listOf<String>()
fun build(whatever: String): Builder {
searchTerms = searchTerms + whatever
return this
}
}
fun main() {
val b = Builder()
val toSearch = listOf<String>("Anna", "Berta", "Carla")
toSearch.forEach{ e-> b.build(e)}
}
Not exactly sure what you consider clumsy about it, but if it's that you have to create a distinct line for the temporary variable, you might consider this cleaner:
fun main() {
val toSearch = listOf<String>("Anna", "Berta", "Carla")
val b = toSearch.fold(Builder()) { builder, e -> builder.build(e) }
}

Create extension function (function with . in name)

I want to generate a very simply class that just contains extension functions, like e.g. following:
import com.my.app.SomeClass
fun SomeClass.function() {
}
What I try:
val packageName = ...
val annotatedClassName = annotatedElement.simpleName
val fileName = "${annotatedClassName}_KotArgsExtensions"
val extensionBuilder = FileSpec.builder(packageName, fileName)
val funSpecBuilder= FunSpec.builder("${SomeClass::class.java.simpleName}.function").build()
extensionBuilder.addImport(SomeClass::class.java.`package`.name, SomeClass::class.java.simpleName)
extensionBuilder.addFunction(funSpecBuilder)
What I get:
import com.my.app.SomeClass
fun `SomeClass.function`() {
}
Question
How I can I correctly create an extension function like fun SomeClass.function()?
Use FunSpec.Builder.receiver():
val builder = FunSpec.builder("function")
.receiver(SomeClass::class)
.build()
println(builder.build().toString())
Will give you:
fun com.my.app.SomeClass.function() {
}