2017-05-23 83 views
0

如果我有一个数组someArray,我第一次想要做一些操作,然后该结果传递给函数arrfun,它接受一个数组作为参数。像下面合格结果的功能

let arr = someArray.filter(foo).map(bar) 
let result = arrfun(arr) 

在上述情况下,我想避免分配给被传递到arrfun中介变量。我想有这样的事情。

Object.prototype.pipe = function(f) {return f(this)} 

let result = someArray.filter(foo).map(bar).pipe(arrfun) 
  • 代替.pipe()的你会如何解决这个问题?
  • 难道是明智的引入功能Object
  • pipe这种功能最好的名字? chainpass

新例如

const pc = options => options 
    .join(' ') 
    .match(/--[\w.]* [\w.]*/g) 
    .map(s => s.slice(2).split(' ')) 
    .map(([key, value]) => ({key, value})) 
    .map(nestObject) 
    .reduce((acc, val) => Object.assign(acc, val), {}) 

const nestObject = ({key, value}) => key 
    .split('.') 
    .reverse() 
    .reduce((inner, key) => ({[key]: inner}), value) 

在上述例子中一个问题是,.match返回null如果没有找到匹配。使用.pipe你可以解决它NY改变该行

.pipe(s => s.match(/--[\w.]* [\w.]*/g) || []) 

你将如何解决这一不pipe

+0

出了什么问题只是'arrfun(someArray.filter (富).MAP(巴))'? – Bergi

+0

如果你真的想在Object.prototype上引入一个新的方法,至少(但不是,[它不是合理的](https)([正确地执行它](http://stackoverflow.com/q/13296340/1048572) ://stackoverflow.com/q/14034180/1048572))。 – Bergi

+0

['chain'](https://github.com/fantasyland/fantasy-land#chain)意思是不同的 – Bergi

回答

2

在上述情况下,我想避免必须分配一个中间变量传递给arrfun

你可以俯瞰这个简单的,直白的表达?

let result = arrfun(someArray.filter(foo).map(bar)) 

从右到左功能组成

或者,也许你想经典(从右到左)函数组合?

const compose = (f,...fs) => x => 
 
    f === undefined ? x : f(compose(...fs)(x)) 
 

 
const filter = f => xs => 
 
    xs.filter(x => f(x)) 
 

 
const map = f => xs => 
 
    xs.map(x => f(x)) 
 

 
const foo = x => 
 
    x > 3 
 
    
 
const bar = x => 
 
    x * x 
 
    
 
const arrfun = xs => 
 
    xs.reverse() 
 

 
const myfunc = 
 
    compose(arrfun, map(bar), filter(foo)) 
 

 
let someArray = [1,2,3,4,5,6] 
 

 
let result = myfunc(someArray) 
 

 
console.log(result) 
 
// [ 36, 25, 16 ]


如上使用左到右功能组合物

相同的答案左到右功能组合物

const compose = (f,...fs) => x => 
 
    f === undefined ? x : compose(...fs)(f(x)) 
 

 
const filter = f => xs => 
 
    xs.filter(x => f(x)) 
 

 
const map = f => xs => 
 
    xs.map(x => f(x)) 
 

 
const foo = x => 
 
    x > 3 
 
    
 
const bar = x => 
 
    x * x 
 
    
 
const arrfun = xs => 
 
    xs.reverse() 
 

 
// notice order of functions 
 
const myfunc = 
 
    compose(filter(foo), map(bar), arrfun) 
 
    
 
let someArray = [1,2,3,4,5,6] 
 

 
let result = myfunc(someArray) 
 

 
console.log(result) 
 
// [ 36, 25, 16 ]


身份仿

我不认为在可读性方面环绕整个事情秤。想象一下,你必须将更多的东西链接到arrfun,然后用另一个函数包装这个东西。

您应该看到this answer我写了一篇关于身份函子 - 这给你一个可链接的接口,但是如果你继续filter不接触本地的原型

const Identity = x => ({ 
 
    runIdentity: x, 
 
    map: f => Identity(f(x)) 
 
}) 
 

 
const foo = x => 
 
    x > 3 
 
    
 
const bar = x => 
 
    x * x 
 
    
 
const arrfun = xs => 
 
    xs.reverse() 
 

 
const myfunc = xs => 
 
    Identity(xs) 
 
    .map(xs => xs.filter(foo)) 
 
    .map(xs => xs.map(bar)) 
 
    .map(xs => arrfun(xs)) 
 
    .runIdentity 
 

 
let someArray = [1,2,3,4,5,6] 
 

 
let result = myfunc(someArray) 
 

 
console.log(result) 
 
// [ 35, 25, 16 ]

当然和如前所定义,它清除了myfunc的定义

const Identity = x => ({ 
 
    runIdentity: x, 
 
    map: f => Identity(f(x)) 
 
}) 
 

 
const filter = f => xs => 
 
    xs.filter(x => f(x)) 
 

 
const map = f => xs => 
 
    xs.map(x => f(x)) 
 

 
const foo = x => 
 
    x > 3 
 
    
 
const bar = x => 
 
    x * x 
 
    
 
const arrfun = xs => 
 
    xs.reverse() 
 

 
const myfunc = x => 
 
    Identity(x) 
 
    .map(filter(foo)) 
 
    .map(map(bar)) 
 
    .map(arrfun) 
 
    .runIdentity 
 

 
let someArray = [1,2,3,4,5,6] 
 

 
let result = myfunc(someArray) 
 

 
console.log(result) 
 
// [ 35, 25, 16 ]

,但没有得到挂在foobar被定义了前面。我们可以使用lambda表达式中myfunc直接,如果你想

const myfunc = xs => 
    Identity(xs) 
    .map(xs => xs.filter(x => x > 3)) 
    .map(xs => xs.map(x => x * x)) 
    .map(arrfun) 
    // or skip defining arrfun somewhere else and just ... 
    // .map(xs => xs.reverse()) 
    .runIdentity 
+0

我不认为在可读性方面包装整个事物。想象一下,你必须将更多的东西链接到arrfun,然后用另一个函数包装这个东西。虽然我可能忽视了作文。唯一可能是缺点的事情可能是我必须先定义函数然后编写(也许是件好事)。 – antonbasic

+0

我更新了我的答案以解决您的评论。 **身份函数**非常适合制作可链接的界面,而无需触摸原生原型。让我知道如果我可以进一步帮助你^ _^ – naomik

+0

关于你的评论编辑,'foo'和'bar'不需要预定义 - 他们可以是直接写在'myfunc'中的lambda表达式。 – naomik

0

你可以先撰写你的手功能,你的结果功能为可重复使用的功能。像:

let arr = [1,2,3,4,5]; 
const manipulatorFn = arr => arr.map(item => item +1); 
const arrFunc = (arr, fn) => fn(arr); 

,或者如果你想要做一些更多的东西在arrFunc

const arrFunc = (arr, fn) => { 
    let a = fn(arr); 

    // do some more stuff with a 
    return a; 
}; 

现在你可以获取你的结果

let result = arrFunc(arr, manipulatorFn);