0

Hey I am working in kotlin tree data Structure. I want to know which leaf node value has minimum price rate value. My whole list is in sorted order. But I am not able to figure out, how can I know which leaf is minimum node. I'll demonstrate you small example because I have bigger data.

when I am pointing parent, I have few children node and their value is in sorted order, but problem is there is some price on it, I want to know which one is minimum and whole list is sending to my adapter android. So I don't understand where I can find minimum node. when I am creating the node or some other place?

                                    2


                    |          |         |          |

value->             1          2         3          4

price value->     4.38        5.8       3.2        6.7

LevelIndex.kt

open class LevelIndex(
    var value: String? = null,
    var children: MutableList<LevelIndex> = arrayListOf()
)  

LevelOne.kt

class LevelOne : LevelIndex() {
}

LevelTwo.kt

class LevelTwo : LevelIndex() {
}

Main.kt

var baseNode: LevelIndex = LevelIndex()

fun main() {
    val list = getUnSortedDataListForLevel() // this retrun ProductLevel Data Class value
    val tempHashMap: MutableMap<String, LevelIndex> = mutableMapOf()
    list.forEach { levelClass ->

        levelClass.levelA?.let { levelA ->
            val levelOneTempHashMapNode = tempHashMap["level_a${levelClass.levelA}"]
            if (levelOneTempHashMapNode != null) {
                return@let
            }
            val tempNode = LevelOne().apply {
                value = levelA
            }
            val parent =
                tempHashMap["level_a${levelClass.levelA}"] ?: baseNode
            parent.children.add(tempNode)
            tempHashMap["level_a${levelClass.levelA}"] =
                tempNode
        }
        levelClass.levelB?.let { levelB ->
            val tempNode = LevelTwo().apply {
                value = levelB
            }
            val parent =
                tempHashMap["level_a${levelClass.levelA}"]
                    ?: baseNode
            parent.children.add(tempNode)
        }
    }
}

when I am pointing to 2 value then I have children value is 1, 2, 3, 4. Can someone suggest me?

UPDATE I forgot to add data class

ProductLevel.kt

data class ProductLevel(
    val id: String? = null,
    val levelA: ProductValue? = null,
    val levelB: ProductValue? = null,
    val price: ProductValue? = null
)

ProductValue.kt

data class ProductValue(
   val value: String? = null,
)

My Data looks like this

ProductLevel(id= "1", levelA= ProductLevel("2"), levelB= ProductLevel("1"), price= "4.38")

ProductLevel(id= "2", levelA= ProductLevel("2"), levelB= ProductLevel("2"), price= "5.8")

ProductLevel(id= "3", levelA= ProductLevel("2"), levelB= ProductLevel("3"), price= "3.2")

ProductLevel(id= "4", levelA= ProductLevel("2"), levelB= ProductLevel("4"), price= "6.7")

After adding this line I am getting this weird error

val result = currentItem.asFlatIterable().minByOrNull(LevelIndex::price)

enter image description here

Kotlin Learner
  • 3,995
  • 6
  • 47
  • 127

1 Answers1

1

I'm not sure I understand exactly. But if you want to search your whole tree because the price property could appear at any level, you could create a flat Iterable using the iterator builder, and then use familiar collection operators on it. This Iterable could be reusable for many purposes for searching your tree. The nice thing about creating it with the iterator builder is that it doesn't have to allocate a list big enough to reference all the nodes of your tree at once.

(The way I created this is with the iterator builder, which uses a suspend function to lazily yield values to a SequenceScope. iterator's lambda is a restricted coroutine, so the inner recursive function I created has to use the SequenceScope as a parameter so the compiler doesn't complain that we're breaking the restrictions on the coroutine.)

fun LevelIndex.asFlatIterable() = Iterable {
    iterator {
        suspend fun SequenceScope<LevelIndex>.yieldChildren(parent: LevelIndex) {
            for (child in parent.children) {
                yield(child)
                yieldChildren(child)
            }
        }
        yieldChildren(this@asFlatIterable)
    }
}

To be able to search by price this way, price needs to be a property on the shared parent class LevelIndex.

val result = root.asFlatIterable().minByOrNull(LevelIndex::price)

This asFlatIterable() could be useful for all kinds of purposes. You could get all nodes matching a certain filter() or map them to a flat List, etc.

Tenfour04
  • 83,111
  • 11
  • 94
  • 154
  • my first question is where can I add the price value? when I am inserting the node value inside this code `val tempNode = LevelTwo().apply { value = levelB }`? – Kotlin Learner Feb 22 '22 at 21:20
  • I added the my data class as well. – Kotlin Learner Feb 22 '22 at 21:21
  • I have no idea what relationship there is between ProductLevel and LevelIndex. – Tenfour04 Feb 22 '22 at 21:22
  • ProductLevel is coming from server and LevelIndex I created for tree reference. – Kotlin Learner Feb 22 '22 at 21:25
  • what is the data type of `.minByOrNull(LevelIndex::price)`of price in this line. If I create `price` attribute inside my `LevelIndex` I choose double. But yout this line it complaining , I am adding error in my question. Please have a look – Kotlin Learner Feb 22 '22 at 21:33
  • Price can be anything that implements Comparable. Your problem once again is using `Double?` instead of `Double`. Don't use nullables unless you absolutely have to. Also, `Double` or `Float` is a bad choice to represent a currency amount because of floating point precision. Floating point primitives cannot hold exact decimal (base 10) fractional amounts because they are represented in binary. Use BigDecimal or Int or Long to store currency. You can use Int or Long if they represent cents. – Tenfour04 Feb 22 '22 at 22:24
  • sorry to be honest. That value is coming from server and sometimes that value can be null. That's why I created nullable type. Ok sure next time, I'll take long value if the value in euro + cents. – Kotlin Learner Feb 22 '22 at 22:30
  • thanks once again it work @Tenfour04. You are genius. – Kotlin Learner Feb 22 '22 at 22:30
  • If it has to be nullable, then you could use `minByOrNull { it.price ?: Double.MAX_VALUE }` or something like that. But it will ignore anything that is missing a price value. – Tenfour04 Feb 22 '22 at 22:31
  • yep I did the same thanks once again. @Tenfour04 – Kotlin Learner Feb 22 '22 at 22:34
  • can you look this [issue](https://stackoverflow.com/q/71254602/11560810) please. – Kotlin Learner Feb 24 '22 at 15:49