2

I am trying to find index of all the instances let's say Header and Footer in an array.

var arr = [
'data',
'data',
'data',
'data',
'Header',
'data',
'data',
'data',
'Footer',
'data',
'Header',
'data',
'Footer',
'data'
];

I know how to do this in plain JS (How to find index of all occurrences of element in array?), but I wonder how it would be done in FP, ramda.js in particular?

I know how to do this for first instance R.findIndex(R.test(_regexForHeader)) but can not wrap my head around looping through all array. Thanks for help.

Community
  • 1
  • 1
qaraluch
  • 25
  • 1
  • 4

2 Answers2

3

@pierrebeitz's answer is on point, namely that when you need access to indices while iterating over a list you'll typically zip the list up along with its indices. Ramda provides an R.addIndex function for modifying functions like map to provide the index along with each element while iterating.

The nesting in his example can also be replaced with a composition pipeline if you prefer:

const zipWithIndex = addIndex(map)(pair);

const isHeaderOrFooter = either(equals('Header'), equals('Footer'));

const hfIndices = pipe(
  zipWithIndex,
  filter(pipe(head, isHeaderOrFooter)),
  map(nth(1))
);

hfIndices(arr);

One thing to be mindful of with both of these approaches is you'll end up iterating over the list multiple times. This won't typically be a problem for a small list, however for larger lists you might want to consider using R.into which effectively fuses the maps and filter together into a transducer that will now take only a single pass over the list (see http://simplectic.com/blog/2015/ramda-transducers-logs/ for a good intro to transducers).

This can be achieved with a small tweak to hfIndices in the above example by swapping the composition from pipe to compose (transducer functions compose in the opposite order) and wrapping it with into.

const hfIndices = into([], compose(
  zipWithIndex,
  filter(pipe(head, isHeaderOrFooter)),
  map(nth(1))
));
Scott Christopher
  • 6,458
  • 23
  • 26
1

i'm not THAT into FP but i believe you have to "generate" the data you want to work with. you have to add an index to afterwards apply your filter:

 var arr = ['data', 'data', 'data', 'data', 'Header', 'data', 'data', 'data', 'Footer', 'data', 'Header', 'data', 'Footer', 'data'];

R.map((e) => e[1], 
  R.filter(val => val[0] == 'Header' || val[0] == 'Footer', 
    R.addIndex(R.map)((e, i) => [e,i], arr)
  )
);
// => [4, 8, 10, 12]

This is not the most elaborate solution, but it should get you going!

pierrebeitz
  • 221
  • 1
  • 7