I frequently encounter problems that can be simplified if the child data structures would include properties belonging to the parent data structure.
what do I mean? Example time!
Let's say I a run an e-commerce store and I want to know for all products the amount of ordered products of a given status. The status of an ordered product item is determined by the status of the order. In the example below there are 8 ordered products Y with the "ready" status (4 in order A and 4 in order B):
const order_a = {
id: 'a',
status: 'ready',
order_lines: [{
id: 'a1',
product_id: 'yyy',
amount: 4
}]
}
const order_b = {
id: 'b',
status: 'ready',
order_lines: [{
id: 'b1',
product_id: 'yyy',
amount: 4
}]
}
A solution could be:
import {map, chain as flatMap, groupBy, compose, prop } from 'ramda'
const get_nbr_ordered_products_per_status = orders => {
// interesting part starts here
const to_wrapped_order_line = order => ol => ({order_line: ol, status: order.status})
// interesting part ends here
return compose(
map(wrapped_order_lines => wrapped_order_lines.reduce((sum,wol) => (sum + wol.amount),0)),
groupBy(prop('status')),
flatMap(order => order.order_lines.map(to_wrapped_order_line(order)))
)
}
(I didn't write a test for this so apologies if there is a bug in the solution!)
A wrapped order line is an order line wrapped with some additional metadata!
In the example above the additional metadata is the status of the order the order line belongs to.
The solution is simple because I introduced a new data structure (i.e. wrapped order line) that included everything I needed.
The old data structure was wrapped with additional metadata!