I'm very new to Kotlin and Android. I have created an array that accepts input from EditText of 10 values separated by commas, however It is a String array and I need a Int array. Any Help would be very Appreciated. Below is my code:
private fun array() {
val ed = findViewById<View>(R.id.et_addNum) as EditText
var text = ed.text.toString()
val array: List<String> = text.split(",")
for (element in array) {
Log.e("elements", element)
storednumber.setText(array.toString())
}
}
If you absolutely sure your Strings are correct numbers you can use mapping like this:
val stringList: List<String> = listOf("1", "2", "3")
val intList: List<Int> = stringList.map { it.toInt() }
or like this if want to avoid throwing NumberFormatException:
val stringList: List<String> = listOf("1", "2", "3")
val intList: List<Int> = stringList.map { it.toIntOrNull() ?: 0 }
Related
I have this Any type of list;
val sendMetas = mutableListOf<Any>()
sendMetas.add(CarType(count = "2",type = 2))
When sending to the server it should go like this;
"Metas": [{
"car_type": {
"count": "1",
"type": 3
}}]
But instead, it goes like this;
"Metas":[{"count":"2","type":2}]
How can I surround with serialize name I have couple more objects like CarType. Thanks.
I handled by turning into JsonObject;
val jsonObject = JsonObject()
jsonObject.addProperty("count", "1")
jsonObject.addProperty("type", 3)
val prepTimeJson = JsonObject()
prepTimeJson.add("car_type", jsonObject)
sendMetas.add(prepTimeJson)
"Metas" field in exptected json is array of "Meta" object, so instead of adding "CarType" instances in "sendMetas" array you should create "Meta" (data)class with "car_type" field, so it'll look like that:
data class Meta (
val car_type: CarType
)
data class CarType (
val count: String,
val type: Int
)
val sendMetas = mutableListOf<Meta>()
sendMetas.add(Meta(car_type = CarType(count = "2",type = 2)))
I have a string separated by ";" like this:
var dataString: String = "Juan;25;Argentina"
And I want to convert it to this sample data class:
data class Person (
var name: String? = "",
var age: Int? = "",
var location: String? = "")
The only way I figured out to that is like this:
var dataString: String = "Juan;25;Argentina"
var fieldList = dataString.split(";").map { it.trim() }
var personItem = Person(fieldList[0], fieldList[1], fieldList[2])
But this is too static, if I then have to add new field to Person data class, I have to manually add fieldList[3]
Which is the most efficient way to do this? (I searched a lot, but couldn't find it :S )
SOLUTION:
//Data in string
val rawData = "name;age;location\nPerson1;20;USA\nPerson2;30;Germany"
//Custom string reader with ";" separator
val customCSV = csvReader { delimiter = ';' }
//String to map list
val parsed = csvReader().readAllWithHeader(rawData)
//Mal list to list of <Person>
val finalData = grass<Person>().harvest(parsed)
for (entry in entryList) {
//entry is an instance of Person
}
EDIT2:
You can obtain field names for header line like this:
var headerLine = ""
for (entry in Person::class.members) {
if (member.name.isNotEmpty())
headerLine += ";${member.name}"
}
headerLine.substring(1)
The string you showed here looks like a CSV dataset. So I think you could use kotlin-grass and kotlin-csv
https://github.com/blackmo18/kotlin-grass
https://github.com/doyaaaaaken/kotlin-csv/
Example:
val rawData = "Person1;20;USA/nPerson1;30;Germany"
val parsed = csvReader().readAllWithHeader(rawData)
val finalData = grass<Person>().harvest(parsed)
I have problem with nesting data class. Here is my data classes:
#Entity(tableName = "categories_table")
data class Category(
var details: String = "",
#PrimaryKey
var id: String = "",
var lastUpdated: Long = -1,
var name: String = "",
var order: Int = -1,
val specialities: ArrayList<String> = arrayListOf()
)
And here is my DB:
I using this code for get data from database:
val valueEventListener = object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
categories.clear()
specialities.clear()
for (cat in snapshot.children){
val category: Category? = cat.getValue(Category::class.java)
for (spec in cat.children){
spec.getValue(String::class.java)?.let { specialities.add(it) }
}
category?.let { categories.add(it) }
}
_categories.value = categories
}
override fun onCancelled(error: DatabaseError) {
throw error.toException()
}
}
categoryRef.addListenerForSingleValueEvent(valueEventListener)
I have red many themes with this problem but can't find solution and always get this error:
Expected a List while deserializing, but got a class java.util.HashMap
Edit
I have a progress)
for (cat in snapshot.children) {
val categoryMap: Map<String, Any> = cat.value as Map<String, Any>
val category = Category(details = categoryMap.getValue("details").toString(), name = categoryMap.getValue("name").toString(),
id = categoryMap.getValue("id").toString(), lastUpdated = categoryMap.getValue("lastUpdated").toString().toLong(),
order = categoryMap.getValue("order").toString().toInt())
categories.add(category)
I'm not sure that i'm parsing map correct, but it's work. Tell me please if i wrong)
The problem seems to come from val specialities: ArrayList<String> = arrayListOf().
In order for the specialties in your database screenshot to be seen as a List, they'd have a defined order with sequential, numeric keys: 0, 1, 2, etc. What you have however is a bunch of keys, each with a value or a nested object, which is translates to Map<String, Object>.
val specialities: Map<String, Object> = mapOf()
This is my JSON:
{"result": {
"product_id": 283946,
"shop_id": 129,
"is_favorite": false,
"item_sold_by": "Quantity",
"item_description": "hello",
"item_size": [
{
"name": "Height",
"value": "29cm"
},
{
"name": "Width",
"value": "52cm"
}
val json = String(responseBody, charset)
val gson = Gson().newBuilder().serializeNulls().create()
val itemsdetailresult = gson.fromJson<ItemDetailJson>(json, genericType<ItemDetailJson>())
Log.v("Test1", json)
Log.v("Test2", itemsdetailresult.toString())
Picasso.get().load(itemsdetailresult.result.pic1).into(itempic)
itemName.text = itemsdetailresult.result.item_name
shopName.text = itemsdetailresult.result.shop_name
itemdescrip.text = itemsdetailresult.result.item_description
itemprice.text = itemsdetailresult.result.price
val obj = JSONObject(json)
val getObject = obj.getJSONObject("result")
val getArray = getObject.getJSONArray("item_size")
var itemSizeArray = ArrayList<ItemSize>()
var itemString = ""
for (i in 0 until getArray.length()) {
val objects: JSONObject
objects = getArray.getJSONObject(i)
val name = objects["name"].toString()
val value = objects["value"].toString()
itemSizeArray.add(ItemSize(name, value))
itemSizeArray.forEach { data ->
itemString = itemString.plus("${data.name} : ${data.value}")
}
}
itemsizename.text = itemString
Log.v("PRINT", itemsizename.toString())
}
I want the output as --> Height: 29cm / width:52cm and so on if there are more values added in the "item_size"array. How can that be achieved in this for loop. I want to keep appending all the values of "name" and "value" in a variable(parameter) in the for loop and use this variable outside of the for loop.
Here you just need to create a custom data model class with the name and value variables.
data class ItemSizeDataModel(
val name: String?,
val value: String?
)
Now in the class where you are fetching the JSON make use of the ItemSizeDataModel to store the itemsize - name and value.
val json = String(responseBody, charset)
val obj = JSONObject(json)
val getObject = obj.getJSONObject("result")
val getArray = getObject.getJSONArray("item_size")
var parameter: String
var itemSizeArray = ArrayList<ItemSizeDataModel>()
for (i in 0 until getArray.length()) {
val objects: JSONObject
objects = getArray.getJSONObject(i)
val name = objects["name"].toString()
val Value = objects["value"].toString()
itemSizeArray.add(ItemSizeDataModel(name = name, value = value))
}
Now you can access the itemSizeArray array list and access the name and value for each index.
For the output Height: 29cm / width:52cm
you can iterate through the loop
var itemString = ""
itemSizeArray.forEach{data->
itemString = itemString.plus("${data.name}:${data.value}/")
}
itemString = itemString.dropLast(1)
I have a class Person:
class Person(var fullName: String, var nickname: String, var age: Int)
In my code, at some point I have a List of Person objects, and a list of nicknames.
var people: List<Person> = listOf(
Person("Adam Asshat", "dontinviteme", 21),
Person("Bob Bowyer", "bob", 37),
Person("Emily Eden", "emily", 22)
)
var invitedToParty: List<String> = listOf("bob", "emily")
Now I want to get a List with only Bob and Emily by using lambda's, but I'm not sure how I'd go about it in Kotlin.
var invitedPeople: List<Person> = // a lambda that results in a list containing only Bob and Emily's objects
In C# I'd probably use LINQ and a .where()-method combined with an == any() but Kotlin doesn't seem to have anything like that from what I've found.
Is this even possible in Kotlin lambda's?
In C# you'd do:
people.Where(p => invitedToParty.Any(s => s == p.nickname));
Likewise in Kotlin, you'd use filter which is like Where and any speaks for it self:
people.filter { p -> invitedToParty.any { it == p.nickname } }
or using contains:
people.filter { invitedToParty.contains(it.nickname) }
You can use the .filter() function to do this:
val invitedPeople: List<Person> = people.filter { it.nickname == "bob" || it.nickname == "emily" }
Or you can do this set-based:
val invitedPeople: List<Person> = people.filter { it.nickname in setOf("bob", "emily") }
You can do this:
val invitedPeople: List<Person> = people.filter { invitedToParty.contains(it.nickname) }