1

Edit:

I had to return a set of passengers who had majority of discounts. The solution to this riddle was as following,

  1. Extract all the passengers count in a Map
  2. Extract all the passengers count in a Map who received discounts.
  3. Then in a loop I had to apply a lambda to find percentage and see if which passengers received discount on majority of the trips.
  4. Add them to a set and return it.

Please see the code below,

fun findDiscountedPassengers(): Set<Passenger> {
    var discountedPassengerList: MutableList<Passenger> = emptyList<Passenger>().toMutableList()
    var passengerTripCountMap = trips.flatMap { it.passengers }.groupingBy { it }.eachCount()
    var passengerDiscountedTripsMap = trips.filter { it.discount != null }
            .flatMap { it: Trip -> it.passengers }
            .groupingBy { it }
            .eachCount()

    val findPercentage = ...

    passengerDiscountedTripsMap.forEach { it: Map.Entry<Passenger, Int> ->
        val totalTripsCount: Double? = passengerTripCountMap.get(it.key)?.toDouble()
        if (findPercentage(it.value.toDouble(), totalTripsCount?:0.0) > majorPercentage) {
            discountedPassengerList.add(it.key)
        }
    }
    return discountedPassengerList.toSet()
}

My code seems a bit more Java-ish than Kotlin since its not that concise/short or optimized. I created two different groups resulting in two Maps; then create a loop to apply rest of the logic. I think allot of the unnecessary steps can be removed.

Example: Conversion of list to set to return the result and so on.

How can I avoid creating two groups resulting in two different maps? What optimizations can I apply from steps 1 to 4? Can I leverage Partition (not sure about the concept) in any way to reduce the number of steps I have taken in the code above?

Thanks.

Ahmed
  • 2,966
  • 7
  • 42
  • 69
  • 1
    I'm not sure if I'm understanding correctly, but the [partition](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/partition.html) operator might be useful here if you want to split a list based on some predicate. E.g. `trips.partition { it.discount != null && it.discount > 0.0 }` will return a Pair of trips with and without a discount. – Damon Baker Jan 14 '19 at 03:18
  • I'm not sure what you're doing there. why do you do an `eachCount` and then only take the keys? Can you share the data structures please? – s1m0nw1 Jan 14 '19 at 07:26
  • If you can do it in java you might want to consider sharing the java (pseudo) code. Code is often more clear than natural language. – leonardkraemer Jan 14 '19 at 07:39
  • Sorry for the confusion. Let me put my complete Solution here along with the Question that I was trying to solve. In a few youll see my Edits in the Question. – Ahmed Jan 15 '19 at 00:04

1 Answers1

1

As already mentioned in the comments, I don't quite understand your use case and I think your usage of groupingBy does not make sense. You're trying to count the number of passengers that appear inside the trips and my suggestion would be:#

val (passengersWithDiscount, passengersWithoutDiscount) = trips.partition { it.discount != null && it.discount > 0.0 }.let { (with, withOut) ->
    val counter = { trips: List<Trip> -> trips.flatMap { it: Trip -> it.passengers }.count() }
    counter(with) to counter(withOut)
}

With partition, we split the data based on the condition. After that, we declare a counter function which transforms a List<Trip> to its number of passengers. This function is then applied on both result lists we got from the partition.

s1m0nw1
  • 76,759
  • 17
  • 167
  • 196