I have 2 implementation which you can see below and I don't see how it can be simplified. Also, maybe I'm missing something about function composition here, I would be glad to get any help.
p.s.: It also would be nice to get rid of arrow functions.
const sections = [
{
key: 'first',
data: [ { key: 'a' }, { key: 'b' } ]
},
{
key: 'second',
data: [ { key: 'c' }, { key: 'd' } ]
},
{
key: 'third',
data: [ { key: 'e' }, { key: 'f' } ]
},
]
const pathToField = (key, sections) =>
sections
.reduce((found, section, parentIndex) =>
compose(
unless(equals(-1), pair(parentIndex)),
findIndex(propEq(key, 'key')),
prop('data')
)(section)
)
pathToField('f', sections)
const findKeyIndex = useWith(findIndex, [propEq(__, 'key'), prop('data')])
const findFieldIndex = curry(
(key, sections) => compose(
converge(pair, [prop('index'), findKeyIndex(key)]),
find(compose(gt(__, -1), findKeyIndex(key))),
addIndex(map)(flip(assoc('index')))
)(sections)
)
findFieldIndex('f', sections)
If I have to simplify this further(and also not use arrow functions) I would do something like:
Explanation of code:
findKeyIndex: This utility function returns theindexof an object with a given key in a data array. It usesR.findIndex,R.propEq, andR.propto achieve this.R.addIndex(R.map)(R.flip(R.assoc('index'))): This part of the code adds an index property to each parent object in the sections array. The index property holds the index of the object in the sections array.R.find(R.compose(R.gt(R.__, -1), findKeyIndex(key))): This part finds the first parent object in the modified sections array where the key is found in its data array. TheR.gt(R.__, -1)condition checks if the index returned byfindKeyIndex(key)is greater than-1, meaning the key was found in the data array.R.converge(R.pair, [R.prop('index'), findKeyIndex(key)]): Finally, this part forms a pair of indices using the parent object's index property and the index of the object with the specified key in the data array. The result is returned as a pair of indices.