Kotlin short-cut to assign value to variable using stream function or other - kotlin

for (i in 0 until result.size){ result[i].config= addConfig(taskNames!![i],processKeys!![i]) }
Here result is a list of class which has datamember config and tasNames and processKeys are list of string.
Is there a way in kotlin to map result.config with respective taskNames and processKeys without using traditional loop and mentioning length of result.I am new to kotlin.
class Process {
var processKey: String? = null
var task: List<Task>? = null}
class Task {
var taskName: String? = null
var processVariables: List<ProcessVariable>? = null}
class ProcessVariable {
var name: String? = null
var label: String? = null
var applicableValue: List<String>? = null}
Result is already present with datamember config pf type ProcessVariable

If I understand your problem correctly, you need to combine 3 lists.
So iterating over the lists may be easier to understand than some clever way of list transformations.
You can get rid of the traditional for loop, so you don't need to calculate the size of the loop:
result.forEachIndexed {
i, resultData -> resultData.config = addConfig(taskNames[i], processKeys[i])
}
If you want to combine two lists, you can use the zip method:
val configList = taskNames.zip(processKeys) {tsk, prc -> addConfig(tsk, prc)}
In your example, the result-object was already existing. Maybe it is easier to create new result-objects:
val results = configList.map {
Result(config = it)
}

Related

Combining Two List in Kotlin with Index

There is a data class as fruits.
data class Fruits(
val code: String, //Unique
val name: String
)
The base list indexed items with boolean variable is as below.
val indexList: MutableList<Boolean> = MutableList(baseFruitList.size) { false }
Now the Favourite Indexed list is as below
val favList: MutableList<Boolean> = MutableList(favFruitList.size) { true}
I want a combined full list which basically has the fav item indicated as true.
Ex:
baseFruitList = {[FT1,apple],[FT2,grapes],[FT3,banana],[FT4,mango],[FT5,pears]}
favList = {[FT2,grapes],[FT4,mango]}
The final index list should have
finalIndexed = {false,true,false,true,false}
How can we achieve in Kotlin, without iterating through each element.
You can do
val finalIndexed = baseFruitList.map { it in favList }
assuming, like #Tenfour04 is asking, that name is guaranteed to be a specific value (including matching case) for a specific code (since that combination is how a data class matches another, e.g. for checking if it's in another list)
If you can't guarantee that, this is safer:
val finalIndexed = baseFruitList.map { fruit ->
favList.any { fav.code == fruit.code }
}
but here you have to iterate over all the favs (at least until you find a match) looking to see if one has the code.
But really, if code is the unique identifier here, why not just store those in your favList?
favList = listOf("FT2", "FT4") // or a Set would be more efficient, and more correct!
val finalIndexed = baseFruitList.map { it.code in favList }
I don't know what you mean about "without iterating through each element" - if you mean without an explicit indexed for loop, then you can use these simple functions like I have here. But there's always some amount of iteration involved. Sets are always an option to help you minimise that

Sum Mutable Map values inside a list of objects kotlin

I have a data class in Kotlin like this:
data class Activity(
var id: String? = "",
var prize: MutableMap<String?, Int?>? = null
)
And a list of this object:
var myList = listOf(Activity("A", prize={day_5=70, day_4=70}),
Activity("B", prize={day_5=40, day_4=80}))
The desired result is:
Activity("A", prize={total=140}),
Activity("B", prize={total=120})
So basically I want to sum the values of the prize map inside of each object.
I think that has something to do with transformation but I'm new to Kotlin and I couldn't find any resources over the internet, or maybe they were to complicated.
This algorithm is easy, just iterating through all the maps and replace elements with the sum:
val myList = listOf(
Activity("A", hashMapOf("day_5" to 70, "day_4" to 70)),
Activity("B", hashMapOf("day_5" to 40, "day_4" to 80)),
)
for (i in myList) {
val total = i.prize.values.sum()
i.prize.clear()
i.prize["total"] = total
}

How to filter elements in one list by a property value not present in elements in another list?

I have the following code snippet
val cachedNews = listOf(News(9, "https://009"), News(8, "https://234"), News(7, "https://345"))
val freshNews = listOf(News(1, "https://123"), News(2, "https://234"), News(3, "https://345"))
val result = freshNews.filter {fresh -> filter(cachedNews, fresh)}
private fun filter(cached: List<News>, fresh: News): Boolean {
cached.forEach { cachedItem ->
if (cachedItem.url == fresh.url) return true
}
return false }
When the code runs if cachedItem.url == fresh.url the list is filtered and the result is a list where the urls of the two lists are identical. However when i reverse equality like so cachedItem.url != fresh.url the list is not filtered at all. The sequence of execution changes.
When using the == sign, the first item of freshNews is compared with the first Item of cachedNews after that the secondItem of freshNews is compared with secondItem of cachedNews and so on.
When I use the != sign the all items of freshNews are compared against only the firstItem of cachedNews ??
Am I missing something or is my code just wrong?
I'm not sure what the specific problem is because your approach is quite confusing. Your custom filter function is actually more like a contains function.
What might be useful is to:
Extract the cached URLs to a set
Filter the new results by URLs that are not in the set.
fun main() {
val cachedNews = listOf(News(9, "https://009"), News(8, "https://234"), News(7, "https://345"))
val freshNews = listOf(News(1, "https://123"), News(2, "https://234"), News(3, "https://345"))
val cachedUrls = cachedNews.map { it.url }.toSet()
val result = freshNews.filterNot { cachedUrls.contains(it.url) }
println(result)
}
Result:
[News(id=1, url=https://123)]

Why filtering out null map keys doesn't change type to not nullable in kotlin?

I have a list of objects with an optional id as String and I want to make a map out of it.
I want to have the keys of my map as non nullable: so something like this:
data class Foo(
val id: String? = null
val someStuff: String? = null,
)
val foo = listOf(Foo("id1"), Foo())
val bar = foo.filterNot { it.id == null }.associateBy { it.id }
Here bar type is Map<String?, Foo> but not Map<String, Foo>
My workaround is to add a non null asserted call: !!, but it doesn't seem clean.
Is there an easy and safe way to do this?
This looks like something that contracts could help with, but currently a contract expression can't access properties of the class in use.
As a workaround, you could define a 2nd class that has a non-null id, like so
data class Foo(
val id: String? = null,
val someStuff: String? = null
)
data class Foo2(
val id: String,
val someStuff: String? = null
)
val foo = listOf(Foo("id1"), Foo())
val bar = foo
.mapNotNull { if (it.id != null) Foo2(it.id, it.someStuff) else null }
.associateBy { it.id }
There's a six-year-old open feature request for Map.filterNotNullKeys() and a four-year old open feature request for Map.associateByNotNull().
In my opinion, the associateBy { it.id!! } would be cleanest for readability. But you could do it like this:
val bar = foo.mapNotNull { it.id?.run { it.id to it } }.toMap()
As for your actual question, that logic is way too many steps for the compiler to infer. Your last function call to associateBy sees a nullable, so it infers a nullable. For the compiler to figure this out, it would have to step back and see that the List that you call associateBy on happens to have filtered out certain objects in a way that happens to ensure that a certain nullable property won't be null within this specific list, and it's the same property that you are associating with. Now imagine it has to do this for every call to any generic function, and the various lambdas involved could potentially have multiple lines of code. Compile times would skyrocket.

How to use jooq to update table when column names and it's values determined at runtime

I have list of table column names and it's values which will be determined # run time. Right now I am using following way to achieve the feet which requires casting Filed to TableField for every single column name. Is there any better way ?
override fun updateFields(job: Job, jsonObject: JsonObject, handler: Handler<AsyncResult<Job?>>): JobQService {
val updateFieldsDsl = dslContext.update(JOB)
var feildSetDsl: UpdateSetMoreStep<*>? = null
jsonObject.map.keys.forEach { column ->
feildSetDsl = if (feildSetDsl == null) {
updateFieldsDsl.set(JOB.field(column) as TableField<Record, Any>, jsonObject.getValue(column))
} else {
feildSetDsl!!.set(JOB.field(column) as TableField<Record, Any>, jsonObject.getValue(column))
}
}
val queryDsl = feildSetDsl!!.where(JOB.ID.eq(job.id))
jdbcClient.rxUpdateWithParams(queryDsl.sql, JsonArray(queryDsl.bindValues)).subscribeBy(
onSuccess = { handler.handle(Future.succeededFuture(job)) },
onError = { handler.handle(Future.failedFuture(it)) }
)
return this;
}
I'm not sure what you mean by "better" but there is a method UpdateSetStep.set(Map), which seems to be helpful for what you're trying to do. See the javadoc:
UpdateSetMoreStep set(Map<?,?> map)
Set a value for a field in the UPDATE statement.
Keys can either be of type String, Name, or Field.
Values can either be of type <T> or Field<T>. jOOQ will attempt to convert values to their corresponding field's type.