kluck
09/04/2019, 9:29 AMdata class Item(val name: String, val quantity: Int)
fun List<Item>.addItem(item: Item): List<Item> { ??? }
listOf(Item("apple", 3), Item("Pear", 1)).addItem(Item("apple", 2) // -> expected : listOf(Item("apple", 5), Item("Pear", 1))
What would be an FP version of addItem
?marstran
09/04/2019, 9:35 AMfun List<Item>.addItem(item: Item): List<Item> = this + item
kluck
09/04/2019, 9:47 AMtginiotis
09/04/2019, 10:08 AMItem
seems like a monoid, but you still have to figure out the list lookup partthan_
09/04/2019, 11:15 AMmikkom
09/04/2019, 12:23 PMfun List<Item>.combineItems(): List<Item> {
val listOfMaps = this.map { mapOf(it.name to it.quantity).k() }
val combinedMap = MapK.monoid<String, Int>(Int.monoid()).run {
listOfMaps.combineAll()
}
return combinedMap.entries.map { Item(it.key, it.value) }
}
fun List<Item>.addItem(item: Item): List<Item> =
(this + item).combineItems()
mikkom
09/04/2019, 12:24 PMkluck
09/04/2019, 12:40 PMfun List<Item>.addItem(item: Item) = (associateBy(Item::name).asSequence() + mapOf(item.name to item).asSequence())
.groupBy({ it.key }, { it.value })
.mapValues { (_, values) ->
values.reduce { acc, item ->
acc.copy(quantity = acc.quantity + item.quantity)
}
}.values.toList()
mikkom
09/04/2019, 12:49 PMmikkom
09/04/2019, 12:50 PMmarstran
09/04/2019, 12:54 PMfun <T> List<T>.mapWhere(predicate: (T) -> Boolean, transform: (T) -> T) =
map { if(pred(it)) transform(it) else it }
Then you can do this:
fun List<Item>.add(item: Item): List<Item> =
if (find { it.name == item.name } != null) {
mapWhere({ it.name == item.name },
{ it.copy(quantity = it.quantity + item.quantity) })
} else {
this + item
}
kluck
09/04/2019, 12:59 PM