Collections
This post provides some of the operations that can be done in the collections using kotlin
The below is the base type definitions that will be used in the below collection queries
data class Shop(val name: String, val customers: List<Customer>)
data class Customer(val name: String, val city: City, val orders: List<Order>) {
override fun toString() = "$name from ${city.name}"
}
data class Order(val products: List<Product>, val isDelivered: Boolean)
data class Product(val name: String, val price: Double) {
override fun toString() = "'$name' for $price"
}
data class City(val name: String) {
override fun toString() = name
}
Operations on collections
// Return a list of customers, sorted in the descending by number of orders they have made
fun Shop.getCustomersSortedByOrders(): List<Customer> =
this.customers.sortedByDescending({ it -> it.orders.count() })
// Find all the different cities the customers are from
fun Shop.getCustomerCities(): Set<City> =
this.customers.map { it -> it.city }.toSet()
// Find the customers living in a given city
fun Shop.getCustomersFrom(city: City): List<Customer> =
this.customers.filter { it -> it.city == city }
// Return true if all customers are from a given city
fun Shop.checkAllCustomersAreFrom(city: City): Boolean =
this.customers.all { it -> it.city == city }
// Return true if there is at least one customer from a given city
fun Shop.hasCustomerFrom(city: City): Boolean =
this.customers.any { it -> it.city == city }
// Return the number of customers from a given city
fun Shop.countCustomersFrom(city: City): Int =
this.customers.filter { it -> it.city == city }.count()
// Return a customer who lives in a given city, or null if there is none
fun Shop.findCustomerFrom(city: City): Customer? {
if (this.hasCustomerFrom(city)) {
return this.customers.find { it.city == city }
} else {
return null
}
}
// Build a map from the customer name to the customer
fun Shop.nameToCustomerMap(): Map<String, Customer> =
this.customers.associateBy { it.name }
// Build a map from the customer to their city
fun Shop.customerToCityMap(): Map<Customer, City> =
this.customers.associateWith { it.city }
// Build a map from the customer name to their city
fun Shop.customerNameToCityMap(): Map<String, City> =
this.customers.associate { it.name to it.city }
// Build a map that stores the customers living in a given city
fun Shop.groupCustomersByCity(): Map<City, List<Customer>> =
this.customers.groupBy { it.city }
// Return customers who have more undelivered orders than delivered
fun Shop.getCustomersWithMoreUndeliveredOrders(): Set<Customer> =
customers.filter {
val (delivered, undelivered) = it.orders.partition { it.isDelivered }
undelivered.size > delivered.size
}.toSet()
// Return all products the given customer has ordered
fun Customer.getOrderedProducts(): List<Product> =
this.orders.flatMap(Order::products)
// Return all products that were ordered by at least one customer
fun Shop.getOrderedProducts(): Set<Product> =
this.customers.flatMap(Customer::getOrderedProducts).toSet()
// Return a customer who has placed the maximum amount of orders
fun Shop.getCustomerWithMaxOrders(): Customer? =
customers.maxByOrNull { it.orders.size }
// Return the most expensive product that has been ordered by the given customer
fun getMostExpensiveProductBy(customer: Customer): Product? =
customer.orders.flatMap { it.products }.maxByOrNull(Product::price)
// Return the sum of prices for all the products ordered by a given customer
fun moneySpentBy(customer: Customer): Double =
customer.orders.flatMap { it.products }.sumOf(Product::price)
// Return the set of products that were ordered by all customers
fun Shop.getProductsOrderedByAll(): Set<Product> {
val allProducts = customers.flatMap { it.getOrderedProducts() }.toSet()
return customers.fold(allProducts) { orderedByAll, customer ->
orderedByAll.intersect(customer.getOrderedProducts())
}
}
fun Customer.getOrderedProducts(): List<Product> =
this.orders.flatMap(Order::products)
// Find the most expensive product among all the delivered products
// ordered by the customer. Use `Order.isDelivered` flag.
fun findMostExpensiveProductBy(customer: Customer): Product? {
return customer.orders.filter { it.isDelivered }.flatMap(Order::products).maxByOrNull(Product::price)
}
// Count the amount of times a product was ordered.
// Note that a customer may order the same product several times.
fun Shop.getNumberOfTimesProductWasOrdered(product: Product): Int {
return customers
.flatMap(Customer::getOrderedProducts)
.count { it == product }
}
fun Customer.getOrderedProducts(): List<Product> =
this.orders.flatMap(Order::products)
// Find the most expensive product among all the delivered products
// ordered by the customer. Use `Order.isDelivered` flag.
fun findMostExpensiveProductBy(customer: Customer): Product? {
return customer
.orders
.asSequence()
.filter(Order::isDelivered)
.flatMap(Order::products)
.maxByOrNull(Product::price)
}
// Count the amount of times a product was ordered.
// Note that a customer may order the same product several times.
fun Shop.getNumberOfTimesProductWasOrdered(product: Product): Int {
return customers
.asSequence()
.flatMap(Customer::getOrderedProducts)
.count { it == product }
}
fun Customer.getOrderedProducts(): Sequence<Product> =
orders.asSequence().flatMap(Order::products)
These are the various operations that we can perform on the collections using Kotlin.
I have solved these Koans in Kotlin web app and posting here for anyone looking for references.
Comments
Post a Comment