How to: ProtoBuf: get the parent message - kotlin

Given a message (b of type B), nested in another (a of type A); how does one get ‘a’?
I was hoping for something like ‘b.getParent()’.
message B { optional string name = 1; repeated B b = 2; }
message A { optional string name = 1; repeated B b = 1; }
Here is an example instance of an ‘a’ with textual serialization.
name: "a"
b { name: “foo”
b { name: “fred”
b { name: “flintstone” }}}
b { name: “bar” }
b { name: “baz” }
The issue is that I am navigating the collection 'a' with a visitor and I need to be able to reconstruct a full name composed of names of all the ancestors.
Refs:
Get the parent message of a protobuf message (in python)
I am fine with internal representation as I will wrap it in a kotlin extension.

You cannot do this. A B has no need of, or attachment to, an A. If you want to track the parents, you must do so explicitly yourself.

There is no good (efficient) way to initialize a backing data structure.
An alternative approach is for the visitor to maintain an Array rather than just a B.
Here is an example:
fun depthFirstVisitor(root: A, fragFilter: (frag: B) -> Boolean): Sequence<Array<B>> {
return sequence {
root.fragmentsList.forEach { child ->
if (fragFilter(child)) {
yield(arrayOf(child))
dfs(emptyArray(), child, fragFilter)
}
}
}
}
private suspend fun SequenceScope<Array<B>>.dfs(
ancestry: Array<B>,
base: B,
fragFilter: (frag: B) -> Boolean
) {
val ancestryNew = ancestry + base
base.fragmentsList.forEach { child ->
if (fragFilter(child)) {
yield(ancestryNew + child)
dfs(ancestryNew, child, fragFilter)
}
}
}
The current B is the last element of the array.
I am using an Array because it does not suffer from type erasure like other containers.

Related

sort an array by providing field name dynamically

I have a data class with about 20 fields:
data class Entry {
entryType: string,
order: int
....
}
now an array is created with the class
val entries = listOf<Entry>(...);
basically, I want to sort the array but user can specify any field they want to sort by. My current attempt appears to be repetitive.
fun sortByOrder(){
entries.sortedWith {f: Entry, s: Entry ->
if (f.order != s.order) {
f.order - s.order
} else {
f.entryType.compareTo(s.entryType)
}
}
}
I couldn't find away of having one method like below that can do it dynamically:
fun sortEntries(fieldName: string, fieldType: string, backUpField: string){
if (fieldType == 'number'){
entries.sortedWith {f: Entry, s: Entry ->
if (f[fieldName] != s[fieldName]) {
f[fieldName] - s[fieldName]
} else {
f[backUpField].compareTo(s[backUpField])
}
}
}
}
how can I achieve something like the above?

Kotlin sort one List with key and Enum with key and order

I receive data from Request information as list data (List) below code. That data has a "key" parameter by which I want to sort it.
data class ApplianceSetting(
#SerializedName("key") val key: String,
#SerializedName("value") var value: Any,
(...)
I have the required order in the SettingsUtilEnum and want to sort items by that.
After that, I can convert the list using map{} the data and use the function of Enum getSettingByMode() and get the list of Enum values. Then I will sort them and convert them again to List.
But that sounds too inefficient. Is there a better way.
enum class SettingsUtilEnum(
var settingKey: String,
override val order: Int = 99,
var settingName: String = "",
) : AbstractOrderEnum {
FIRST_MODE("first.mode", 0),
SECOND_MODE("second.mode", 1),
(...)
UNKNOWN_MODE("", 99);
companion object {
#JvmStatic
fun getSettingByMode(settingKey: String): SettingsUtilEnum? {
return values().find { it.settingKey == settingKey }
}
k
private fun initDataObserver() {
(activity as FavouriteActivity).viewModel.applianceSettings.observe(activity as FavouriteActivity
) { data ->
(controlRecyclerView.adapter as FavouriteAdditionalControlsAdapter)
val adapter = (controlRecyclerView.adapter as FavouriteAdditionalControlsAdapter)
// public final var data: List<ApplianceSetting>
// old code:
// data.settings
adapter.data = sortAndGetControlModes(data)
adapter.notifyDataSetChanged()
}
}
// TODO: sortAndGetControlModes
private fun sortAndGetControlModes(data: ApplianceSettingsList) =
data.settings.map {
getSettingByMode(it.key)
?: UNKNOWN_MODE.apply {
// If in future new modes are added -> put them as tail
settingKey = it.key
}
}.sortedBy { it.order }
// error i need to return again List<ApplianceSetting>
If you want to compare keys with theirs ASCII values you can just use sortBy { it.key }
If you want to expand possibilities of comparison you can use function sortedWith with passing custom comparator as argument.
Comparator used to compare its two arguments for order. Returns zero if the arguments are equal, a negative number if the first argument is less than the second, or a positive number if the first argument is greater than the second.
Example:
You can use it like that if you want to sort by integer value of key parameter:
data.settings.sortedWith { a, b ->
when {
a.key.toInt() < b.key.toInt() -> -1
a.key.toInt() > b.key.toInt() -> 1
else -> 0
}
}
I fixed it using sortedBy and as comparator I am using received value (order) from getSettingByMode(), if item is not found (null) I give him order value of 99 and put it on tail position:
private fun sortAndGetControlModes(data: ApplianceSettingsList) =
data.settings.sortedBy {
getSettingByMode(it.key)?.order ?:99
}

Finding an item in a list of lists that can contain many levels

kotlin 1.4.72
I have the following class that contains a list. However, the list will contain another list and could be 3 or 4 levels deep.
I am populating the data structure like this. And have a method to find a item from one of the children.
data class Producer(
val id: Int,
val children: List<Producer> = emptyList(),
) {
fun createProducer(src: Producer): Producer {
return Producer(
id = src.id,
children = src.children.map {
createProducer(it)
}
)
}
fun findProducerByIDorNull(id: Int): Producer? {
val producer = children.firstOrNull {
it.id == id
}
return producer
}
}
Currently I am using firstOrNull. However, that will only find the item in the 1st level. If the item is at a 3 level it will return null.
Just wondering if there is a better way to do this.
Many thanks for any suggestions,
You could make findProducerByIDOrNull recursive. Something like:
fun findProducerByIDorNull(id: Int): Producer? {
if (this.id == id) {
return this
}
return children.asSequence()
.mapNotNull { it.findProducerByIDorNull(id) }
.firstOrNull()
}

Transform a List of One Type To Another

I have a list of type A. I want to turn it into a list of type B.
fun publish(listOne: List<A>) {
val result: List<B> =
}
Class B looks like this. It has a constructor that if you pass A then it will copy the variables and make a new instance of B.
class B(name: String ....) {
constructor(a: A) {
// copies the values of a then creates an instance.
}
}
How can I use this constructor to make a new list of type B? Normally I would traverse the entire list of and make a new instance of B per instance of A. However, is there a way to do this in Kotlin that is easy?
You can just map the given list:
val result: List<B> = listOne.map(::B)
// or
val result: List<B> = listOne.map { B(it) }

Real use of generic in typescript

I don't get what is the actual use of generics in typescirpt.
interface ICustomer
{
name: string;
age: number;
}
function CalcAverageAge<c extends ICustomer>(cust1: c, cust2: c): number
{
return (cust1.age + cust2.age)/2;
}
resNumber = CalcAverageCustomerAge({name: "Peter", age: 62},
{name: "Jason", age: 33});
In the above example we are passing interface c to function CalcAverageAge.
But without using extends ICustomer we can't use age and name inside that class.
Then what is the use of passing template( c ) in the function.
We can directly write the code in below format
function CalcAverageAge(cust1: ICustomer, cust2: ICustomer): number
{
return (cust1.age + cust2.age)/2;
}
Can you give a real example where generics is really useful?
I will explain you my scenario where I need to use generics.
interface t1{
a:String
b:number
}
interface t2 {
a:String
b:number
c:number
}
interface t3 {
a:String
b:number
d:number
}
class base<T extends t1> {
constructor( input : T, type:string ){
//some common code for both derived1 and derived2
if(type==="derived1"){
console.log(input.c);// will throw error because t1 doesn't contains c
} else if ( type==="derived2"){
console.log(input.d);// will throw error because t1 doesn't contains d
}
}
}
class derived1 extends<t2>{
constructor(){
var temp = {a:"11",b:2,c:3}
super(temp,"derived1");
}
class derived2 extends<t3>{
constructor(){
var temp = {a:"11",b:2,d:3}
super(temp,"derived2");
}
}
Can we achieve this with generice?
If not what would be the best way of implementation avoiding duplicate codes.
In your example it is correct that the interface is all you need.
Generics is something that is useful when you want to make something generic; sometimes it might be so generic that you do not even need an interface. The example you bring up is not only a generic, it also limits what the generic can look like with an interface.
Other examples of what a generic can be used for is a collection that can contain any type of item. The array type in typescript is an example of that - var a = new Array<number>() - for example.
But say that you want to create a function that compares two items, something like this:
interface IValue { value: number; }
function max(a: IValue, b: IValue): IValue {
return a.value > b.value ? a : b;
}
In this case you have the issue that the max function returns its result as an IValue In most cases this is not what you want. What you want is something like this:
interface IValue { value: number; }
function max<T extends IValue>(a: T, b: T): T {
return a.value > b.value ? a : b;
}
Here the return type of max is whatever the generic type T is, and this is more useful.