1

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

3
  • At some point of time splitFormule contains only one element. Check it. Commented Dec 12, 2018 at 11:32
  • 1
    what did you expect? you may want to debug it and you will see the problem... could it be that your string doesn't contain any ` = `? Commented Dec 12, 2018 at 11:33
  • Yes @Rolan, it was that. It forgot to add this condition. Thanks, I feel kind of stupid ^^' Commented Dec 12, 2018 at 11:40

2 Answers 2

3

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
Sign up to request clarification or add additional context in comments.

2 Comments

you may want to use splitToSequence instead of split otherwise you create a new list on each map-call, which you basically discard all when you call toMap...
Thank you very much @Roland! I was not aware of that. Made me read this interesting article about collections vs. sequences: blog.kotlin-academy.com/…
1

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()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.