Helpme nested lists in map

Hello friends, I need to find the content of a map using the key, show the content of the value, and with the same key be able to delete and also modify. I tried with flatmap, but I don’t know how to implement it.


package com.example.pruebas.oop.clases

import kotlin.String


class Producto (val detalle:String?="", val pciounit:Double?=0.00, val pciovta:Double?=0.00, val rubro: Int?=0) {
    //operator fun component1() = mid
    val productoMapa = mutableMapOf<String, ArrayList<Producto>>()
    val productoArray = ArrayList<Producto>()

    fun alta(code:String, item: Producto) {
        productoArray.add(item)
        productoMapa.put(code, productoArray)
   }


///////////////Funcion VER
                fun ver() {
                        println(productoMapa.size)
                        var n=0
                    for ((key,value)in productoMapa) {
                            println("${key} ${value[n].detalle}${value[n].pciounit} ${value[n].pciovta} ${value[n].rubro}")
                       n=n+1
                        }
                           }
///////////////Funcion Buscar
fun buscar(clave:String) {
    val matchingKey = productoMapa.entries.find { it.key == clave } ?.key
}


}
fun main(){
    val producto=Producto()
    alta(producto)
    buscar(producto)
}

fun alta(prod:Producto) {
    prod.alta("001",Producto("Etchard Blanco x 1000cc", 5.01, 6.25, 1))
    prod.alta("002",Producto("Zucardi Tinto x 1000cc", 6.54, 7.15, 1))
    prod.alta("003",Producto("Mirk Tinto x 750cc", 6.33, 7.33, 1))
    prod.alta("004",Producto("Bless Rosado x 750cc", 6.56, 7.25, 1))
    prod.alta("005",Producto("Mel Tinto x 1000cc", 5.15, 7.38, 1))
    prod.alta("006",Producto("Etchar Blanco x 750cc", 4.34, 6.38, 2))
    prod.alta("007",Producto("Toro Blanco x 1000cc", 6.78, 7.38, 2))
    prod.alta("008",Producto("Tupungato Blanco x 750cc", 3.23, 5.38, 2))
    prod.alta("009",Producto("Bizterry Blanco x 1000cc", 4.55, 8.38, 2))
    prod.alta("010",Producto("Rivoli Blanco x 350gr", 4.34, 6.38, 3))
    prod.alta("011",Producto("Wero Blanco x 500gr", 6.78, 7.38, 3))
    prod.alta("012",Producto("Palmiro Blanco x 350gr", 3.23, 5.38,3))
    prod.alta("013",Producto("Tiken Blanco x 500gr", 4.55, 4.55, 3))

    //prod.ver()
}

fun baja(prod:Producto){
    //prod.baja(Producto("003", "Mirk Tinto x 750cc", 6.33, 7.33, 1))
   // prod.ver()
}

fun buscar(prod:Producto)
{
 prod.buscar("005")

}

The code has some problems.

  • It would be nice to use English identifiers, that makes it much easier to help.
  • Then, you really, really need to understand what belongs into the Producto class and what not. Producto is a single entry, everything managing different products etc. needs to be outside, either in a top-level value, or in an object representing the whole product “table”. In Producto, you would put only stuff like changing the name of this particular product or so (if it were modifiable).
  • You always pass non-null arguments to Producto, so please use non-nullable types, e.g. String instead of String?, else you have to do unnecessary null checks all the time.
  • I don’t really understand why you need an additional ArrayList. You can get all values of a map, you don’t need a separate data structure for this.

This is how the skeleton of your code could look like (it is just one way to do it, it really depends on your use case):

data class Product(val name:String, val pciounit:Double, val pciovta:Double, val rubro: Int)

object ProductTable {
    val productMap = mutableMap(
       "001" to Product("Etchard Blanco x 1000cc", 5.01, 6.25, 1),
       "002" to Product("Zucardi Tinto x 1000cc", 6.54, 7.15, 1),
       ...  
    )

    fun get(key: String): Product? {...}
    
    fun getAll(): List<Product> {...} 

    fun add(key: String, product: Product) { ... }

    fun delete(key){ ... } 
}


fun main() {
   // just an example
   var p = ProductTable.get("002")
   if (p != null) println(p) else println("not found") // prints product

   ProductTable.delete("002")

   p = ProductTable.get("002")
   if (p != null) println(p) else println("not found") // prints "not found"
}

Please understand that I don’t want to give you the full solution, give it a try first, and people will help you with this.

But I think you need to understand first why a product map doesn’t belong in Product, that is in my opinion the most important step, because else you end up in total confusion.

3 Likes

I think Landei has given a pretty good explanation, but I wanted to chime in with a few of my own thoughts.

My main thought is that unless your code isn’t structured correctly, you have a Map of Producto inside the Producto class. So you create a Producto instance, then store other Producto instances inside it. I don’t think that’s intended?

My other main thought is that I don’t think you know how Lists and pointers work.

    val productoMapa = mutableMapOf<String, ArrayList<Producto>>()
    val productoArray = ArrayList<Producto>()

    fun alta(code:String, item: Producto) {
        productoArray.add(item)
        productoMapa.put(code, productoArray)
   }

The way that this code works, is you create ONE list. Then every time you call the alta function, it adds the item to the SAME list. It then adds an entry to the Map, where the key is the String you provided, and the value is a pointer to the list. So what you will end up with is a Map full of keys that all point to the same list.

3 Likes

It was actually easier, with some simple codes I achieved the result, I am new to Kotlin, I am learning

data class Product(val detalle:String?="", val pciounit:Double?=0.00, val pciovta:Double?=0.00, val rubro: Int?=0) {
    
    val productTable = mutableMapOf<String, Product>()
    
    
    fun alta(code:String, item: Product) {
       productTable.put(code, item)
    }

fun buscar(clave:String) {

            productTable.get(clave)
            println(productTable.getValue(clave).detalle)

}


fun alta(prod:Product) {
    prod.alta("001",Product("Etchard Blanco x 1000cc", 5.01, 6.25, 1))
    prod.alta("002",Product("Zucardi Tinto x 1000cc", 6.54, 7.15, 1))
    prod.alta("003",Product("Mirk Tinto x 750cc", 6.33, 7.33, 1))

Now two people have tried to explain that the productTable doesn’t belong in the Product class, and you do it anyway. It kind of works, but think about what you are doing: You create one product, the one that you are passing to the alto function. It contains a map of products itself. Then you add the first product “Etchard Blanco” to this map, but of course every product has a product table map, so this one has a product map (which is not used) and the next one has a product map, and the next one as well.

Sometimes such recursive data types make sense, e.g. if you want to have a binary tree or a linked list. It makes even sense if you have a item that consists of other parts, like having a car as an item which has “sub-items” like wheels and an engine etc., and you end up with a tree-like structure again. But your products are just that, they have no parts, they don’t need to know about a map of other products, because they are not related. So for the love of god, take the productTable out of Product, put it in a top-level val, or in an object.

If you insist on keeping productTable inside of Product, you can do it that way, but I’m almost certain that this will confuse you more than it will help:

data class Product(val detalle:String, val pciounit:Double, val pciovta:Double, val rubro: Int) {
    companion object {   
        val productTable = mutableMapOf<String, Product>()
        
        fun alta(code:String, item: Product) {
           productTable[code] = item
        }

        fun buscar(clave:String) {
            println(productTable[clave].detalle)
       }
    }
}

fun main() {
   Product.alta("001",Product("Etchard Blanco x 1000cc", 5.01, 6.25, 1)
}

Notice how I don’t have to create a product first to call alta? There is only one productTable now, and you can access it from everywhere.

2 Likes

Well, I didn’t know about the companion object, now I’ll study it and try it, thanks