Hey fellow programmers,
I recently jumped from my normal python programming to Kotlin programming in Android Studio.
In python I have generated some dictionaries that contain strings as keys and tuples as values. These tuples theirselves then contain an int, two strings and again two ints. Imagine this simplified dict:
dict = {"key" : (1,"firstString","secondString",2,0),
"secondKey":(0,"firstString","secondString",4,1)}
Now comes the scary part: I would like to import my dicts into normal variables/ vals in Kotlin.
Therefore I put all four dicts I have in a text file in the res folder. The difficulty for me is both declaring the val of the appropriate data structure and then actually loading the key-value-pairs step by step into the val. All Kotlin tutorials seem to come to an end when diving this deep into their data structures.
Am I right in guessing I should have a hashmap for the dicts themselves and then a(n array) list for the tuples? Got even stuck when trying to declare that complex structure:
val importedDict: HashMap<String,Array<Integer,String,String,Integer>> = hashMapOf<String,Array<Int,String,String,Int>()
as there just seemed to be no valid data structure of multiple types in Kotlin.
I'm thankful for any hint you can give.
I believe the easiest way to represent your tuples is to declare a data class, like so:
data class TupleData(val id: Int,
val firstString: String,
val secondString: String,
val otherNumber: Int,
val anotherNumber: Int)
And then declare your data structure as HashMap<String, TupleData>. Note that you have to think about nullability of the types (String or String?) and if they have immutable references (val or var) since you didn't specify them in your question.
Also, to make your life easier, I believe you could use Moshi with a custom adapter to parse your string as if it was a JSON object directly into your data structures. (but keep in mind this other answer).
You cannot declare an Array as Array<Integer, String, String, Integer> because it takes only one generic parameter named T in the kotlin documentation. If you want to specify a tuple you either have to use Pair or Triple and if there's more data than that in the tuple, declare a data class
EDIT: After trying to make a working example with your data, I noticed that it's not properly formatted for JSON parsing, so you'll probably have to parse them by hand.
If you still want to look into how to serialize into JSON (maybe using pickle from Python), this is how I implemented the adapter:
class TupleDataAdapter {
@ToJson
fun toJson(tupleData: TupleData) : String {
val (id, first, second, other, another) = tupleData;
return "($id, $first, $second, $other, $another)"
}
@FromJson
fun fromJson(tuple: String) : TupleData {
if (tuple[0] != '(' || tuple.last() != ')') {
throw JsonDataException("Wrong format for tuple data: missing '(' or ')'")
}
val trimmed = tuple.trimStart('(').trimEnd(')')
val fields = trimmed.split(',')
if (fields.size != 5) {
throw JsonDataException("Wrong format for tuple data: wrong number of fields in tuple")
}
return TupleData(fields[0].toInt(), fields[1], fields[2], fields[3].toInt(), fields[4].toInt())
}
}
fun main(args: Array<String>) {
val dict = File("./dict.txt").readText()
println(dict)
val moshi = Moshi.Builder()
.add(TupleDataAdapter())
.build()
val type = Types.newParameterizedType(Map::class.java, String::class.java, TupleData::class.java)
val mapAdapter : JsonAdapter<Map<String, TupleData>> = moshi.adapter(type)
val decoded : Map<String, TupleData>? = mapAdapter.fromJson(dict)
println(decoded)
}
This implementation worked correctly when I changed the text as such:
{"key" : "(1,firstString,secondString,2,0)","secondKey" : "(0,firstString,secondString,4,1)"}
Note the difference in the quotation marks.
Array can only contain one type of data so multiple types cannot be declared instead, use Array<Any> where Any is super class of every object so use
var map : Map<String, Array<Any>> = mapOf("key" to arrayOf(1,"firstString","secondString",2,0))
You can declare the array if you want to add values like
var map2 : HashMap<String, Array<Any>> = HashMap<String, Array<Any>>()
map2.put("key" , arrayOf(1,"firstString","secondString",2,0))
println(map2["key"]?.get(2)) // "secondString"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With