Projet Sin
Projet Sin

Reputation: 357

Kotlin : string to array to key value

I'm trying to create a key => value Hashmap.

First, I have a string delimited by <br />. Then, I split it with split() (to get each string independently).

Then, I need to split each result with "=". The first part will be the key (I need it to be a string) and the second one will be the value (an int)

For now I have

val formules = objInput.getString(Constants.formules)
val hashmap = HashMap<String, Int>()
val resSplit = formules.split("<br />")
    resSplit.forEach {
      val splitFormule = it.split(" = ")
      val key = splitFormule.elementAt(0)
      val value = splitFormule.elementAt(1)
      Log.i(TAG, "$key")
}

I have this error when I'm trying to display the value :

Index: 1, Size: 1

Upvotes: 1

Views: 5580

Answers (2)

Patric
Patric

Reputation: 1627

Be careful that your input is correct. Whitespaces are relevant. <br /> is different from <br/> and = is different from <space>=<space>. Assuming your input looks like this:

foo = 3<br />bar = 5<br />baz = 9000

Then you can create a map using this simple expression:

val map = formules
    .splitToSequence ("<br />") // returns sequence of strings: [foo = 3, bar = 5, baz = 9000]
    .map { it.split(" = ") } // returns list of lists: [[foo, 3 ], [bar, 5 ], [baz, 9000]]
    .map { it[0] to it[1] } // return list of pairs: [(foo, 3), (bar, 5), (baz, 9000)]
    .toMap() // creates a map from your pairs

Upvotes: 3

Roland
Roland

Reputation: 23232

As you already said, you forgot a condition to check whether your string even contains a =.

Some furter notes: you can replace your elementAt also with get or with the indexing operator (e.g. splitFormule[0]).

You may also be interested in destructuring, e.g. your split could also be written as follows:

val (key, value) = it.split(" = ") // no need to extract the values from the array, if you know how the splitted data looks like
// you may even want to use the following if there could potentially be more than 1 '=' in the value part
val (key, value) = it.split(" = ", limit = 2) // at most 2 parts

Finally another variant, which skips keys if there aren't any values associated to them:

val yourMap = formules.splitToSequence("<br />")
    .filter { it.contains("=") }
    .map { it.split("""\s*=\s*""".toRegex(), limit = 2) }
    .map { (key, value) -> key to value } // destructuring
    .toMap()

// or: instead of filtering do a takeif and if you require those keys, do something appropriate there (e.g. set a default value instead)
val yourMap = formules.splitToSequence("<br />")
    .map { it.split("""\s*=\s*""".toRegex(), limit = 2) }
    .mapNotNull { it.takeIf { it.size == 2 } } // this discards now the entries without any value
    .map { (key, value) -> key to value } // destructuring
    .toMap()

Upvotes: 1

Related Questions