您好我正在学习Ramda
图书馆并喜欢它。我正在尝试练习一些功能性概念,例如curry
和immutability
。下面我有一些代码,它基本上试图assoc
来自一个object
的值并将其复制到另一个object
。第一个object
kdlJsonObj
具有cost
值,我想将其附加到另一个对象
//object from API
var kdlJsonObj = [
{name: 'AAA COOPER TRANSPORTATION', cost: 33},
{name: 'OLD DOMINION FREIGHT LINE, INC', cost: 22},
{name: 'ROADRUNNER TRANSPORTATION SERVICES', cost: 31}
]
// objects to assoc
var aaa = {shortName: 'AAA Cooper', name: 'AAA COOPER TRANSPORTATION' }
var odlf = {shortName: 'Old Dominion', name: 'OLD DOMINION FREIGHT LINE, INC'}
var rr = {shortName: 'Road Runner', name: 'ROADRUNNER TRANSPORTATION SERVICES'}
// Ramda functions that I would like to compose
var namePropEq = R.propEq('name')
var namePropEqAAA = namePropEq('AAA COOPER TRANSPORTATION')
var findAAA = R.find(namePropEqAAA, kdlJsonObj)
var costProp = R.prop('cost')
var costAAA = costProp(findAAA)
var assocCost = R.assoc('cost')
var assocCostAAA = assocCost(costAAA)(aaa)
assocCostAAA // => {shortName: "AAA Cooper", name: "AAA COOPER TRANSPORTATION", cost: 33}
我希望能够编写这些功能集,使其成为一种更无点的编码风格,在我拨打电话之前不会提供任何数据。理想情况下,它会像var assocCostAAA = composeAssoc(namePropEqAAA)(aaa)
,我只能调用一个函数。由于arity规则
compose
此功能是否可行
var composeAssoc = R.compose(
R.assoc('cost'),
R.find(name, kdlJsonObj), // has two arity so i believe this is not correct
R.propEq(name))
我愿意采取不同的方式。例如使用Ramda
等R.pluck
函数,R.filter
甚至R.lens
。但我希望它能成为一个组合/声明的功能。
答案 0 :(得分:2)
我希望有更优雅的方式,但这是无点的:
const source = [
{ name: 'Aaa', cost: 1 },
{ name: 'Bee', cost: 2 },
{ name: 'Cee', cost: 3 },
];
const target = { shortName: 'A', name: 'Aaa' };
const func =
R.chain(
R.assoc('cost'), // ('cost', 1, target) -> output
R.compose(
R.prop('cost'), // ('cost', {name: 'Aaa', cost: 1}) -> 1
R.compose(
R.find(R.__, source), // (predicate, source) -> {name: 'Aaa', cost: 1}
R.compose(
R.propEq('name'), // ('name', 'Aaa' ) -> predicate
R.prop('name'), // ('name', target) -> 'Aaa'
),
),
),
);
const targetWithCost = func(target);
输出:{"cost": 1, "name": "Aaa", "shortName": "A"}
哦,是的......这有点好一点:
const func =
R.chain(
R.assoc('cost'), // ('cost', 1, target) -> :)
R.compose(
R.prop('cost'), // ('cost', {name: 'Aaa', cost: 1}) -> 1
R.find(R.__, source), // (predicate, source) -> {name: 'Aaa', cost: 1}
R.eqProps('name'), // ('name', target) -> predicate
),
);
输出:{"cost": 1, "name": "Aaa", "shortName": "A"}
斯科特指出我的解决方案并非完全无点,所以作为一个实验,我想出了这个完全无点的代码:
const func =
R.converge(
R.assoc('cost'), // ('cost', 1, target) -> {shortName: 'A', name: 'Aaa', cost: 1}
[
R.useWith( // (target, source) -> 1
R.compose( // (predicate, source) -> 1
R.prop('cost'), // ('cost', {name: 'Aaa', cost: 1}) -> 1
R.find, // (predicate, source) -> {name: 'Aaa', cost: 1}
),
[
R.eqProps('name'), // ('name', target) -> predicate
R.identity, // source -> source
],
),
R.identity, // (target, source) -> target
],
);
const targetWithCost = func(target, source);
答案 1 :(得分:2)
这样做非常简单而不用担心无点:
const {curry, assoc, prop, find, eqProps} = R;
const kdlJsonObj = [
{name: 'AAA COOPER TRANSPORTATION', cost: 33},
{name: 'OLD DOMINION FREIGHT LINE, INC', cost: 22},
{name: 'ROADRUNNER TRANSPORTATION SERVICES', cost: 31}
]
const companies = [
{shortName: 'AAA Cooper', name: 'AAA COOPER TRANSPORTATION' },
{shortName: 'Old Dominion', name: 'OLD DOMINION FREIGHT LINE, INC'},
{shortName: 'Road Runner', name: 'ROADRUNNER TRANSPORTATION SERVICES'},
{shortName: 'Flintstone', name: 'FRED FLINTSTONE HAULING'}
]
const [aaa, odfl, rr, ff] = companies
const addCost = curry((costs, company) => assoc(
'cost',
prop('cost', find(eqProps('name', company), costs)),
company
))
console.log(addCost(kdlJsonObj)(rr))

<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
&#13;
虽然这可以毫无意义地进行,但结果的可读性可能会低得多。我试着将无点作为一种工具,当它(并且只有当它)增加可读性时使用,但你的里程可能会有所不同。
这也不会进行任何真正的错误检查。如果找不到匹配值,则只添加cost: undefined
。
还要注意这是多么脆弱。在帖子中,两个版本的AAA之间的拼写有所不同。如果它们不是从同一来源生成的,那么如果您依赖于长字符串之间的匹配,则可能会出现这样的问题。我对此没有特别的建议,但值得研究。
答案 2 :(得分:0)
@Scott Sauyet我稍微更新了你的一些原因。 1)我在NetSuite上,他们使用Rhino 6
未使用ES6
规范。 2)我是新手,所以虽然我喜欢你非常简洁的风格,但是我把它打破了一点,所以我可以更好地理解它。谢谢您的帮助。
var kdlJsonObj = [
{name: 'AAA COOPER TRANSPORTATION', cost: 33},
{name: 'OLD DOMINION FREIGHT LINE, INC', cost: 22},
{name: 'ROADRUNNER TRANSPORTATION SERVICES', cost: 31}
]
var aaa = {shortName: 'AAA Cooper', name: 'AAA COOPER TRANSPORTATION' }
var odlf = {shortName: 'Old Dominion', name: 'OLD DOMINION FREIGHT LINE, INC'}
var rr = {shortName: 'Road Runner', name: 'ROADRUNNER TRANSPORTATION SERVICES'}
var addCost = function(costs, company) {
var comp = R.find(R.eqProps('name', company), costs)
var cost = R.prop('cost', comp)
return R.assoc('cost', cost, company)
}
var addCostCurried = R.curry(addCost)(kdlJsonObj)
var rrAssocatied = addCostCurried(rr)
var odflAssocatied = addCostCurried(odlf)
var aaaAssocatied = addCostCurried(aaa)