Home > other >  How can I write a function for an order Analysis that will take array of different object data types
How can I write a function for an order Analysis that will take array of different object data types

Time:06-05

Please, how would you get the average for quantity of the same date from the following data in kotlin. A function to take this input and return an object with {"Monday" : 3.40, "Tuesday": 4.5} and a brief explanation how to pass the data into the function (because it doesn't have specific task) will be much appreciated.

        mapOf(
            "orderId" to 554,
            "creationDate" to "2017-03-25T10:35:20",
            "orderLines" to arrayOf(
                mapOf("productId" to 9872, "name" to "pencil", "quantity" to 3, "unitPrice" to 3.00)
            )
        ),
        mapOf(
            "orderId" to 555,
            "creationDate" to "2017-03-25T11:24:20",
            "orderLines" to arrayOf(
                mapOf("productId" to 9872, "name" to "Pencil", "quantity" to 1, "unitPrice" to 3.00),
                mapOf("productId" to 1746, "name" to "Eraser", "quantity" to 1, "unitPrice" to 1.00)
            )
        ),
        mapOf(
            "orderId" to 453,
            "creationDate" to "2017-03-27T14:53:12",
            "orderLines" to arrayOf(
                mapOf("productId" to 5723, "name" to "Pen", "quantity" to 4, "unitPrice" to 4.22),
                mapOf("productId" to 9872, "name" to "Pencil", "quantity" to 3, "unitPrice" to 3.12),
                mapOf("productId" to 3433, "name" to "Erasers Set", "quantity" to 1, "unitPrice" to 6.15)
            )
        ),
        mapOf(
            "orderId" to 690,
            "creationDate" to "2017-03-26T11:14:00",
            "orderLines" to arrayOf(
                mapOf("productId" to 9872, "name" to "pencil", "quantity" to 4, "unitPrice" to 3.12),
                mapOf("productId" to 4098, "name" to "Marker", "quantity" to 5, "unitPrice" to 4.50)
            )
        )```

CodePudding user response:

Using Maps containing a bunch of unrelated types is a bad idea, you're not supposed to do that in a statically typed language like Kotlin (and you lose a lot of the advantages of static typing if you do). Having an unstructured pile of Anys that you have to cast to the type you think it should be when you need to use it, that's asking for trouble.

You'd be better using classes instead, define your data:

data class OrderLine(
    val productId: Int,
    val name: String,
    val quantity: Int,
    val unitPrice: Float // *I don't recommend using floats for this*, see below
}

data class Order(
    val orderId: Int,
    val creationDate: String, // or you could parse it to a Date so you can work with it
    val orderLines: List<OrderLine>
)

Now you can create your data using a data structure instead of a random collection of stuff that may or may not contain valid data (there are no guarantees with a Map<Any>)

Order(
    orderId = 554, // you don't need the parameter names, just using them for comparison
    creationDate = "2017-03-25T11:24:20",
    orderLines = listOf(
        OrderLine(productId = 9872, name = "pencil", quantity = 3, unitPrice = 3.00f)
    )
)

And then you can easily do work on your data. You could add a function on your Order class that gives you the total item quantity for each order:

Order(...) {
    fun getTotalQuantity() = orderLines.sumOf(OrderLine::quantity)
    // or even better, as a property
    val totalQuantity: Int get() = orderLines.sumOf { it.quantity } // same as above
}

// use that to sum all the order totals
val total = orders.sumOf { it.totalQuantity }

or you could just run a function over the whole set of data

val total = orders.sumOf { order ->
    order.orderLines.sumOf { orderLine -> orderLine.quantity }
}

As for the price thing, you shouldn't use floats and doubles for monetary stuff - it's inaccurate and the errors can add up when you're working with a bunch of them. In your case, instead of having a unit price of 3.00, I'd use an Int and call it 300 (cents or whatever). That way it's always exactly the right number, and you can divide by 100 for display purposes

  • Related