How to group by Arraylist multidimensional - kotlin

how do I group by "group" when located in the sub model?
i tried do this, but it error result
mtop.groupBy { it.sub[0].group }
this my code
// my model
data class mTop(val kategori : String, val sub : ArrayList<mSub>)
data class mSub(val id_menu : String, val nama_menu : String, val gambar : String, val group : String)
// my activity
val mtop: ArrayList<mTop> = ArrayList()
val msub: ArrayList<mSub> = ArrayList()
mtop.add(mTop(header, msub))
sorry I often ask on this forum but never helped others, because I'm a beginner and my English is bad. Thank You

mtop.groupBy { it.sub[0].group }
The error you are getting is because sub is empty and you are trying to get the first element.
What you can probably do is to do a filter before trying to groupBy:
mtop.filter{it.sub.isNotEmpty()}.groupBy{it.sub[0].group}

Related

How to use Lucene's DistinctValuesCollector?

My objective is to collect distinct values of select fields to provided them as filter options for the frontend. DistinctValuesCollector seems to be the tool for this, however since I haven't found code sample and documentation except for the Javadocs I can't currently correctly construct this collector. Can anyone provide an example?
This is my attempt which doesn't deliver the desired distinct values of the field PROJEKTSTATUS.name.
val groupSelector = TermGroupSelector(PROJEKTSTATUS.name)
val searchGroup = SearchGroup<BytesRef>()
val valueSelector = TermGroupSelector(PROJEKTSTATUS.name)
val groups = mutableListOf(searchGroup)
val distinctValuesCollector = DistinctValuesCollector(groupSelector, groups, valueSelector)
That field is indexed as follows:
document.add(TextField(PROJEKTSTATUS.name, aggregat.projektstatus, YES))
document.add(SortedDocValuesField(PROJEKTSTATUS.name, BytesRef(aggregat.projektstatus)))
Thanks to #andrewJames's hint to a test class I could figure it out:
fun IndexSearcher.collectFilterOptions(query: Query, field: String, topNGroups: Int = 128, mapper: Function<String?, String?> = Function { it }): Set<String?> {
val firstPassGroupingCollector = FirstPassGroupingCollector(TermGroupSelector(field), Sort(), topNGroups)
search(query, firstPassGroupingCollector)
val topGroups = firstPassGroupingCollector.getTopGroups(0)
val groupSelector = firstPassGroupingCollector.groupSelector
val distinctValuesCollector = DistinctValuesCollector(groupSelector, topGroups, groupSelector)
search(query, distinctValuesCollector)
return distinctValuesCollector.groups.map { mapper.apply(it.groupValue.utf8ToString()) }.toSet()
}

Kotlin : How to use Kotlin Room to generate a unique id

in my application ,apart from the primarykey of a user ,I will still need to generate a unique ID(12 -15 charactors) for showing to the public .
I am new with Room ,Could you please take a look my code ?
Thank you so much in advance !
#Entity
data class UserInfo(
#PrimaryKey(autoGenerate = true)
val userId:Int = 0,
val image: String,
val imageSource : String,//Local or Online
val username : String,
val gender :String,
val userPublicId:String, //this is the id that need to generate 12-15
val birthday : String,
val userIntro :String,
)
As mentioned #Tenfour04 you can use some ways to generate random string. I think org.apache.commons.lang3.RandomStringUtils is a good choice. For exmaple look at the following methods: randomAscii, randomAlphabetic, randomAlphanumeric.

Is there a way to lazy-init a costly field in a specific constructor?

I have a data class I want to populate, where in one constructor I have the data already, and in another I would like to fetch it only when it is required, which is rare.
A sample code would be:
data class Source1(val str1: String)
data class Source2(val str2: String)
data class DTO(val data1: String, val data2: String) {
// ctor which does not need laziness
constructor(source1: Source1) : this(
data1 = source1.str1,
data2 = source1.str1
)
// ctor which needs costly data
constructor(source2: Source2, costlyData: String) : this(
data1 = source2.str2,
data2 = costlyData
)
}
fun demo() {
val source1 = Source1("some str - 1")
DTO(source1)
val source2 = Source2("some str - 2")
val costlyData: String = costlyOperation() // this is the operation I'd like to execute lazily
DTO(source2, costlyData)
}
I'd say the easiest way would be to accept a function as a constructor parameter, something like this:
class DTO(provider:()->String){
constructor(data: String):this({data})
val data by lazy{ provider()}
}
So you can use it in both ways:
val eager = DTO("some str - 1")
val lazy = DTO(::costlyOperation)
A bit nicer way is to have a Source abstraction with different implementations for providing a constant value and performing an operation. But the overall idea would be the same.
Although I wouldn't call this DTO anymore and it loses its data class capabilities regarding the content.

Kotlin ArrayList won't append object using 'add' method

When trying to 'add' a custom object to an ArrayList, the ArrayList remains null
I've tried modifying the data class initialization by using MutableLists, among other things
Here is the data class that I'm using:
data class WYRStatistics(val team: String, val league: String, val gp: String, val g: String, val a: String, val pt: String, val pim: String, val pm: String)
This is where I'm using the data class to construct on object and try to add the object to an ArrayList
var n = 0
var statsArr: ArrayList<WYRStatistics>? = null
while (n < tempStats.length()) {
val statObject = tempStats.getJSONObject(n)
val singleStat = WYRStatistics(statObject.getString("Team"),
statObject.getString("League"),
statObject.getString("GamesPlayed"),
statObject.getString("Goals"),
statObject.getString("Assists"),
statObject.getString("Points"),
statObject.getString("PenaltyMinutes"),
statObject.getString("PlusMinus")
)
println(singleStat)
statsArr?.add(singleStat)
println(statsArr)
tempPlayer.stats?.add(singleStat)
println(tempPlayer)
n++
}
The utilization is inside of a function that handles the asynchronous task of decoding JSON. This is all working fine.
tempStats is a JSONArray - when printed it is formatted properly
When I println singleStat, the object is printed properly
However, when I 'add' singleStat to statsArr, the statsArr returns null
You are initializing arrayList to nullas what JB mentioned.
The correct way should be
val statsArr = arrayListOf<WYRStatistics>()

get a list of parsed json elements

I parsed a json string to the following object structure using gson:
data class Base (
val expand: String,
val startAt: Long,
val maxResults: Long,
val total: Long,
val issues: List<Issue>
)
data class Issue (
val expand: String,
val id: String,
val self: String,
val key: String,
val fields: Fields
)
data class Fields (
val summary: String,
val issuetype: Issuetype,
val customfield10006: Long? = null,
val created: String,
val customfield11201: String? = null,
val status: Status,
val customfield10002: Customfield10002? = null,
val customfield10003: String? = null
)
Everything works fine and also the object model is correct, because I can access each element of the object.
However, I encountered the problem that I dont know how to get a list of all field-elements. Right now, I have only figured out how to access one item (by using an index and get()-function):
val baseObject = gson.fromJson(response, Base::class.java)
val fieldsList = baseObject.issues.get(0).fields
I actually want to have a list of all field elements and not just one. Is there a gson function allowing me to do that? I couldn't find anything about it in the gson documentation for java.
You don't have to look for some gson function when you've already created a baseObject. You just need to get from each issue it's fields and you can use a map function to achieve this, it will convert each issue to a new type so you can get issue fields there
val fieldFromAllIssues: List<Fields> = baseObject.issues.map { it.fields }
it in this context is a one issue. More explanation about it is here