Ramda映射并在一个循环中过滤

时间:2018-04-09 11:40:32

标签: javascript node.js ramda.js

const R = require('rambda')

export const test = () => {

  const data = [1, 2, 3, 4, 5, 6, 7, 8]
  const filter = no => no > 5
  const map = no => no * 100

  // looping 2 times
  return data
    .filter(filter)
    .map(map)

  // wird 1 loop
  return data.reduce((data, no) => {
    if (!filter(no)) return data
    data.push(map(no))
    return data
  }, [])

  // I want to do something like this.
  return data.map(R.pipe(map, filter))

}

您好,是否可以使用ramda或rambda在一个循环中进行映射和过滤?

我的例子:

return data.map(R.pipe(map, filter))

正在返回

Array [
  600,
  700,
  800,
  true,
  true,
  true,
  true,
  true,
  true,
  true,
  true,
]

我需要它[600, 700, 800]

2 个答案:

答案 0 :(得分:4)

您可以使用Ramda' transducers执行此操作。

(免责声明:我是Ramda的作者)

虽然常规Ramda函数的正常组合将循环用于每个列表转换,但是转换的将在每次迭代时运行组合中的每个函数。请注意,由于技术原因,使用传感器时,组合物的运行顺序相反。

并非每个功能都是换能器。文档使用此注释表示一个:"如果在列表位置给出变压器,则用作传感器。"这包含在mapfilter中。有几个功能可以更容易地使用传感器。 into就是其中之一。

尽管如此,编写自己的filterMap函数可能更容易。难道不是很难:

const filterMap = curry((f, m, data) => reduce(
  (a, i) => f(i) ? append(m(i), a) : a, 
[], data))



const {compose, map, filter, into, curry, reduce, append} = R;

const data = [1, 2, 3, 4, 5, 6, 7, 8]
const gt5 = no => {console.log(`filter: ${no}`); return no > 5;}
const times100 = no => {console.log(`map ${no}`); return no * 100;}

console.log('========= Plain composition =========')
const transform1 = compose(map(times100), filter(gt5))
console.log(transform1(data))

console.log('========== With transducers =========')
const transform2 = into([], compose(filter(gt5), map(times100)));
console.log(transform2(data))

console.log('=========== With filterMap ==========')
const filterMap = curry((f, m, data) => reduce((a, i) => f(i) ? append(m(i), a) : a, [], data))
console.log(filterMap(gt5, times100)(data))

<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
&#13;
&#13;
&#13;

如果您想了解换能器是如何发光的,请在合成的末尾添加take(2)

这些为Ramda的实现增加了很多复杂性,并且有一些关于删除它们或试图找到使它们成为可选方法的讨论。但对此并没有做多少。

答案 1 :(得分:0)

当然可以。

const expr = R.compose(
    R.map(x => x * 100),
    R.filter(x => x > 5)
);
const result = expr([1, 2, 3, 4, 5, 6, 7, 8]);
console.log(result);

更新:一个循环方式:

const iter = (acc, x) => (x > 5 && acc.push(x * 100), acc)
const result = R.reduce(iter, [], [1, 2, 3, 4, 5, 6, 7, 8])

单循环或双循环,执行相同的逻辑,应该没有区别。