简体   繁体   English

Ramda地图和过滤器在一个循环

[英]Ramda map and filter in one loop

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

}

Hello, is it possible to map and filter in one loop using ramda or rambda? 您好,是否可以使用ramda或rambda在一个循环中进行映射和过滤?

My example: 我的例子:

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

is returning 回来了

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

and I need it to be [600, 700, 800] 我需要是[600, 700, 800]

You can do this with Ramda's transducers . 您可以使用Ramda的传感器进行此操作。

(Disclaimer: I'm a Ramda author) (免责声明:我是Ramda作家)

While a normal composition of regular Ramda functions will loop for every list transformation, a transduced one will run each function in the composition on each iteration. 常规的Ramda函数的常规组合会在每次列表转换时循环,而经过转换的函数会在每次迭代时运行组合中的每个函数。 Note that for technical reasons, the composition runs in the reverse order when using transducers. 请注意,由于技术原因,使用换能器时,合成顺序相反。

Not every function is a transducer. 并非每个功能都是传感器。 The documentation uses this note to indicate one: "Acts as a transducer if a transformer is given in list position." 文档使用此注释来表示一个注释:“如果在列表中给出了变压器,则充当传感器。” This is included in both map and filter . 这包括在mapfilter There are several functions that make it easier to work with transducers. 有多种功能使使用换能器变得更加容易。 into is one of them. into就是其中之一。

Still, it might be easier to write your own filterMap function. 不过,编写自己的filterMap函数可能会更容易。 Is isn't hard: 并不难:

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> 

If you want to see how the transducers shine, add a take(2) to the end of the composition. 如果要查看换能器如何发光,请在合成的末尾添加take(2)

These add a great deal of complexity to Ramda's implementations, and there has been some talk of removing them, or trying to find a way to make them optional. 这些给Ramda的实现增加了很多复杂性,并且有人谈论删除它们,或者试图找到一种使它们成为可选方法的方法。 But not much has been done toward this. 但是对此并没有做太多的事情。

Of course it can be. 当然可以。

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

updated: a one-loop way: 更新:单循环方式:

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

Both one-loop or two-loop, execute the same logic, should no difference. 无论是单循环还是双循环,执行相同的逻辑,都应该没有区别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM