Kotlin - How do I sum specific element in list? - kotlin

val total = mutableListOf("NO", "NO", "1", "2", "3", "4")
I want to sum which only can cast to int
In this case "1", "2", "3", "4"
Is there any quick way in Kotlin?

you can just use sumBy like this:
total.sumBy { it.toIntOrNull() ?: 0 }

Related

Kotlin - switching object detail based on group by

For example I have a class with below json format
[
{
"name": "a",
"detail": [
"1",
"2",
"3"
]
},
{
"name": "b",
"detail": [
"2",
"3",
"4"
]
}
]
how to change grouped it based on the detail?
[
{
"detail": "1",
"name": [
"a"
]
},
{
"detail": "2",
"name": [
"a",
"b"
]
},
{
"detail": "3",
"name": [
"a",
"b"
]
},
{
"detail": "4",
"name": [
"b"
]
}
]
below is my class structure
data class funName(
#field:JsonProperty("name")
val name: String = "",
#field:JsonProperty("detail")
val detail: Array<String> = arrayOf(""),
)
and my object is based on the array of funName
val data: Array<funName> = ...
i really have no idea how to do it.
val convert = data.groupBy { x -> x.detail } ??
Is this doable in kotlin/java?
Since the original data is grouped by name, you can think of the original data as a list of pairs
name detail
a 1
a 2
a 3
b 2
b 3
b 4
Mapping it to this format first would make it very easy to group by the second thing (detail) in the pair.
Since each funName corresponds to multiple pairs like this, you should use flatMap on data.
val result = data.flatMap { funName ->
funName.detail.map { funName.name to it }
}
.groupBy(keySelector = { (name, detail) -> detail }, valueTransform = { (name, detail) -> name })
// or more concisely, but less readable
// .groupBy({ it.second }) { it.first }
This will get you a Map<String, List<String>>.
If you want a List<Result>, where Result is something like
data class Result(
val detail: String = "",
val names: List<String> = listOf(),
)
You can add an additional map:
.map { (k, v) -> Result(k, v) }

kotlin merge list of map

I want to group by id.
[
{
"id": 1,
"name": "a"
},
{
"id": 2,
"name": "b"
},
{
"id": 3,
"name": "c"
}
]
The results should be as follows:
{
"1": "a",
"2": "b",
"3": "c"
}
What is the most idiomatic way of doing this in Kotlin?
Your question only shows JSON, so I'm not sure if this is about JSON serialization or Kotlin. Since it's tagged kotlin, I'm assuming you're already deserializing the initial list to Kotlin with something like this
data class NamedThing(val id: Int, val name: String)
val list: List<NamedThing> = TODO("somehow you're getting a list of those here")
If you already have this, you can easily create a map from this list using:
val map = list.associate { it.id to it.name }

Appending a new array to a JSON object with SQL Server

I would like to append an array to a JSON object:
JSON object:
{ "value1": "test" }
Array to be appended:
{ "array2": ["1", "2", "3"] }
Expected result:
{ "value1": "test", "array2": ["1", "2", "3"] }
My attempts with JSON_MODIFY failed:
Attempt #1:
SELECT
JSON_MODIFY('{ "value1": "test" }',
'append $.array2',
JSON_QUERY('[ "1", "2", "3" ]'))
-- { "value1": "test", "array2": [["1", "2", "3"]] }
-- An array within an array is appended
Attempt #2:
SELECT
JSON_MODIFY('{ "value1": "test" }',
'append $',
JSON_QUERY('{"array2": [ "1", "2", "3" ]}'))
-- { "value1": "test" }
-- Result doesn't contain the array at all
You are trying to set a property, not appending items to array so remove the append keyword:
SELECT JSON_MODIFY(
'{"value1": "test"}',
'$.array2',
JSON_QUERY('["1", "2", "3"]')
)
-- {"value1": "test","array2":["1", "2", "3"]}

Comparing json in Karate

I have two jsons array responses with same data but the attributes are different. How to compare this kind of jsons.
json 1:
comments: [
{
"onetag1": "1",
"onetag2": "2"
},
{
"onetag11": "3",
"onetage12": "4"
}
]
json 2:
newcommentslist: [
{
"newtag2": "2",
"newtag1": "1"
},
{
"newtag11": "3",
"newtage12": "4"
}
]
Use JsonPath:
* def first = [ { "onetag1": "1", "onetag2": "2" }, { "onetag11": "3", "onetage12": "4" } ]
* def values = $first[*].*
* match values == ['1', '2', '3', '4']
Or transform one of them: https://stackoverflow.com/a/53120851/143475

Kotlin elegant way to mutate List<Triple<String, String, String> to Triple<List<String>, List<String>, List<String>>

I'd like, as succinctly (yet clearly) as possible to transform a List<Triple<String, String, String> to a Triple<List<String>, List<String>, List<String>>.
For instance, say the method performing the transformation is called turnOver, I'd expect:
val matches = listOf(
Triple("a", "1", "foo"),
Triple("b", "2", "bar"),
Triple("c", "3", "baz"),
Triple("d", "4", "qux")
)
val expected = Triple(
listOf("a", "b", "c", "d"),
listOf("1", "2", "3", "4"),
listOf("foo", "bar", "baz", "qux")
)
matches.turnOver() == expected // true
How to write a succinct, clear, and possibly functional turnOver function?
It's ok to use Arrow-Kt, I already got it as project dependency.
fun turnOver(matches: List<Triple<String, String, String>>) = Triple(
matches.map { it.first },
matches.map { it.second },
matches.map { it.third },
)
would be one obvious solution I reckon.
To the best of my knowledge, there is no way in kotlin stdlib to create a Pair or a Triple out of an iterable, array, or sequence. I believe this is deliberate. So I guess the one above is the clearest possible solution.