如何找到数组中所有元素出现的索引(Ramda.js 方式)?
How to find index of all occurrences of an element in array (Ramda.js way)?
我正在尝试查找数组中所有实例的索引,比方说 Header
和 Footer
。
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))
));
我正在尝试查找数组中所有实例的索引,比方说 Header
和 Footer
。
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))
));