首页 > 解决方案 > 使用 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.buildingundefined,有时features.improvements会空

repl.it 上的附加代码/工作台

我可以这样做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-fpor rambda(或任何我可以尝试理解的好文档)编写的解决方案持开放态度,因为这些解决方案可能会提供更简洁的代码,因为它们比标准更面向功能/咖喱lodash

标签: functional-programminglodashramda.js

解决方案


洛达什

这是一个使用的解决方案_.flow()

  1. _.values()使用、_.flatten()和将特征转换为数组(当 时_.compact()忽略)。buildingundefined
  2. id用 转换为 s数组_.map()
  3. 使用 获取值_.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>

拉姆达

  1. 使用获取值、展平和过滤undefinedR.identity
  2. 获取id道具R.map
  3. 使用翻转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>


推荐阅读