我想对对象中的数组执行一些更新,然后根据此更新计算另一个参数。这是我尝试过的:
import * as R from 'ramda'
const obj = {
arr: [
2,
3
],
result: {
sumOfDoubled: 0
}
};
const double = a => {
return a*2;
}
const arrLens = R.lensProp('arr');
const res0sumOfDblLens = R.lensPath(['result','sumOfDoubled']);
const calc = R.pipe(
R.over(arrLens,R.map(double)),
R.view(arrLens),
R.sum,
R.set(res0sumOfDblLens)
);
const updatedObjA = calc(obj);
const updatedObjB = R.set(res0sumOfDblLens,R.sum(R.view(arrLens,R.over(arrLens,R.map(double),obj))),obj);
// what I want: {"arr":[4,6],"result":{"sumOfDoubled":10}}
console.log(JSON.stringify(obj)); //{"arr":[2,3],"result":{"sumOfDoubled":0}}, as expected
console.log(JSON.stringify(updatedObjA)); //undefined
console.log(JSON.stringify(updatedObjB)); //{"arr":[2,3],"result":{"sumOfDoubled":10}}, correct result but the array did not update
我意识到这两种方法都行不通;方法A归结为R.set(res0sumOfDblLens,10)
,这没有意义,因为它没有操作的目标对象。另一方面,方法B对基础对象进行了两次操作,而不是将第一次操作的结果作为第二次操作的输入。
如何仅使用一个功能组合来实现此目的?即将double()
函数应用于对象的一部分,然后将更新后的对象作为输入来计算sumOfDoubled
?
答案 0 :(得分:3)
与OriDrori的converge
解决方案一样,您也可以使用其他两个Ramda函数之一。我总是喜欢lift
胜过nginx: [warn] the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:1
nginx: [emerg] PEM_read_bio_X509_AUX("/etc/ssl/certs/surveyspan.crt") failed (SSL: error:0909006C:PEM routines:get_name:no start line:Expecting: TRUSTED CERTIFICATE)
nginx: configuration file /etc/nginx/nginx.conf test failed
的情况;感觉更像是标准FP,其中converge
非常像Ramda制品。由于converge
的某些可变参数,它并不总是能胜任。但这确实在这里,您可以编写:
converge
但是,这两种解决方案中的identity
都让我想知道是否还有更好的东西。还有。 Ramda的chain
应用于函数时,有时也称为八哥组合器const calc = pipe (
over (arrLens, map (multiply (2))),
lift (set (res0sumOfDblLens) ) (
pipe (view (arrLens), sum),
identity
)
)
。或者说另一种方式,:: (a -> b -> c) -> (a -> b) -> a -> c
。这就是我们要在此处应用的内容。因此,使用chain (f, g) //~> (x) => f (g (x)) (x)
,可以进一步简化:
chain
const arrLens = lensProp('arr')
const res0sumOfDblLens = lensPath(['result', 'sumOfDoubled'])
const calc = pipe (
over (arrLens, map (multiply (2))),
chain (
set (res0sumOfDblLens),
pipe (view (arrLens), sum)
)
)
const obj = { arr: [2, 3], result: { sumOfDoubled: 0 }}
console .log (calc (obj))
答案 1 :(得分:2)
要获取更新的值和对象,以便设置新的总和,可以使用R.converge()
:
const arrLens = R.lensProp('arr');
const res0sumOfDblLens = R.lensPath(['result', 'sumOfDoubled']);
const calc = R.pipe(
R.over(arrLens, R.map(R.multiply(2))),
R.converge(R.set(res0sumOfDblLens), [
R.pipe(R.view(arrLens), R.sum),
R.identity
])
);
const obj = { arr: [2, 3], result: { sumOfDoubled: 0 }};
const result = calc(obj);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
答案 2 :(得分:0)
也许没有镜头的变体更适合您的情况?
const doubleArr = pipe(
path(['arr']),
map(x => x*2)
)
const newData = applySpec({
arr: doubleArr,
result: {
sumOfDoubled: pipe(
doubleArr,
sum
)
}
})