如何找到数组中所有元素出现的索引(Ramda.js 方式)?

How to find index of all occurrences of an element in array (Ramda.js way)?

我正在尝试查找数组中所有实例的索引,比方说 HeaderFooter

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

我知道如何在纯 JS (How to find index of all occurrences of element in array?) 中执行此操作,但我想知道如何在 FP 中执行此操作,尤其是 ramda.js

我知道如何在第一个实例中执行此操作 R.findIndex(R.test(_regexForHeader)) 但无法绕过所有数组循环。感谢帮助。

我不太喜欢 FP,但我相信您必须 "generate" 您想要使用的数据。您必须添加一个索引才能在之后应用您的过滤器:

 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]

这不是最详尽的解决方案,但它应该能让您继续前进!

@pierrebeitz 的回答是中肯的,即当您需要在遍历列表时访问索引时,您通常会将列表与其索引一起压缩。 Ramda 提供了一个 R.addIndex 函数来修改像 map 这样的函数,以便在迭代时提供索引以及每个元素。

如果您愿意,他的示例中的嵌套也可以替换为组合管道:

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);

使用这两种方法需要注意的一件事是您最终会多次遍历列表。对于较小的列表,这通常不是问题,但是对于较大的列表,您可能需要考虑使用 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/ 来很好地介绍传感器)。

这可以通过对上述示例中的 hfIndices 进行一些小的调整来实现,方法是将组合从 pipe 交换为 compose(换能器函数以相反的顺序组合)并换行它与 into.

const hfIndices = into([], compose(
  zipWithIndex,
  filter(pipe(head, isHeaderOrFooter)),
  map(nth(1))
));