functional-programming - 使用 lodash(或 ramda)拆分/嵌套 _.flow
问题描述
我有两个对象,一个描述features
一个位置,另一个描述prices
这些特征。
features = {
improvements: [...] // any array of many id's
building: {} // only one id, may be undefined
}
prices = {
id_1: 10,
...
}
我想迭代features
并整理所有prices
. 有时features.building
会undefined
,有时features.improvements
会空。
我可以这样做lodash
:
result = _(features.improvements)
.map(feature => prices[feature.id])
.concat(_.cond([
[_.isObject, () => prices[features.building.id]]
])(features.building)) // would like to clean this up
.compact()
.value();
我有兴趣以更实用的方式写这个,我最终得到:
result = _.flow([
_.partialRight(_.map, feature => prices[feature.id]),
_.partialRight(_.concat, _.cond([
[_.isObject, () => prices[features.building.id]]
])(features.building)),
_.compact,
])(features.improvements)
我仍然几乎要偷偷打电话features.building
到中流,这让我觉得很尴尬。
我想要的是(伪编码):
flow([
// maybe need some kind of "split([[val, funcs], [val, funcs]])?
// the below doesn't work because the first
// flow's result ends up in the second
// do the improvement getting
flow([
_.map(feature => prices[feature.id])
])(_.get('improvements')),
// do the building getting
flow([
_.cond([
[_.isObject, () => [argument.id]]
])
])(_.get('building')),
// concat and compact the results of both gets
_.concat,
_.compact,
])(features); // just passing the root object in
可能吗?一个更有经验的 FP 程序员将如何处理这个问题?
我对使用lodash-fp
or rambda
(或任何我可以尝试理解的好文档)编写的解决方案持开放态度,因为这些解决方案可能会提供更简洁的代码,因为它们比标准更面向功能/咖喱lodash
。
解决方案
洛达什
这是一个使用的解决方案_.flow()
:
_.values()
使用、_.flatten()
和将特征转换为数组(当 时_.compact()
忽略)。building
undefined
id
用 转换为 s数组_.map()
。- 使用 获取值
_.at()
。
const { values, flatten, compact, partialRight: pr, map, partial, at } = _;
const fn = prices => _.flow([
values,
flatten,
compact,
pr(map, 'id'),
partial(at, prices)
])
const prices = {
i_1: 'cost_i_1',
i_2: 'cost_i_2',
i_3: 'cost_i_3',
i_4: 'cost_i_4',
b_1: 'cost_b_1',
};
const features = {
improvements: [
{id: 'i_1'},
{id: 'i_2'},
{id: 'i_3'},
{id: 'i_4'},
],
building: {
id: 'b_1'
},
};
const result = fn(prices)(features);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
lodash/fp
const { values, flatten, compact, map, propertyOf } = _;
const fn = prices => _.flow([
values,
flatten,
compact,
map('id'),
map(propertyOf(prices))
])
const prices = {"i_1":"cost_i_1","i_2":"cost_i_2","i_3":"cost_i_3","i_4":"cost_i_4","b_1":"cost_b_1"};
const features = {"improvements":[{"id":"i_1"},{"id":"i_2"},{"id":"i_3"},{"id":"i_4"}],"building":{"id":"b_1"}};
const result = fn(prices)(features);
console.log(result);
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>
拉姆达
- 使用获取值、展平和过滤
undefined
器R.identity
。 - 获取
id
道具R.map
。 - 使用翻转
R.props
来获取 ids 值prices
const { pipe, values, flatten, filter, identity, map, prop, flip, props } = R;
const propsOf = flip(props);
const fn = prices => pipe(
values,
flatten,
filter(identity),
map(prop('id')),
propsOf(prices)
);
const prices = {"i_1":"cost_i_1","i_2":"cost_i_2","i_3":"cost_i_3","i_4":"cost_i_4","b_1":"cost_b_1"};
const features = {"improvements":[{"id":"i_1"},{"id":"i_2"},{"id":"i_3"},{"id":"i_4"}],"building":{"id":"b_1"}};
const result = fn(prices)(features);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
推荐阅读
- python-3.x - 如何使用 protobuf 文本作为参数在 python 上发送 http post 请求?
- neo4j - Cypher - 具有可选匹配的聚合
- windows - 怎么解压gz文件?
- javascript - “for循环”中的Bootrstrap事件
- ios - 使用 json 的一部分进行快速解码
- tensorflow - Conv3d 预测抛出错误输入深度必须能被过滤器深度整除:1 vs 3
- javascript - 在 Postman 预请求脚本中获取 Azure REST 访问令牌
- python - 我在 Seaborn 桌子上的 X 轴上的标签不正确
- sql - SQL:返回分页记录并获取所有记录的计数
- python - 如何在 python 的 ascii 中打印 32 个控制字符?