Functional programming 含lodash(或ramda)的分流/嵌套流

Functional programming 含lodash(或ramda)的分流/嵌套流,functional-programming,lodash,ramda.js,Functional Programming,Lodash,Ramda.js,我有两个对象,一个描述位置的功能,另一个描述这些功能的价格 features = { improvements: [...] // any array of many id's building: {} // only one id, may be undefined } prices = { id_1: 10, ... } 我想反复浏览功能并整理所有价格有时功能。建筑将未定义,有时功能。改进将为空 我可以用lodash这样做: result = _(features.imp

我有两个对象,一个描述位置的
功能
,另一个描述这些功能的
价格

features = {
  improvements: [...] // any array of many id's
  building: {} // only one id, may be undefined
}
prices = {
  id_1: 10,
  ...
}
我想反复浏览
功能
并整理所有
价格
有时
功能。建筑
未定义
,有时
功能。改进
将为空

我可以用
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)
我仍然不得不几乎秘密地调用
功能。在中流中构建
,这让我感觉很尴尬

我想说的是(伪编码):

可能吗?一个经验丰富的FP程序员将如何处理这个问题


我对使用
lodash fp
rambda
编写的解决方案持开放态度(或任何我可以尝试理解的好文档),因为这些解决方案可能会提供更清晰的代码,因为它们比标准的
lodash
更加面向功能/通用

下面是一个使用
.flow()
的解决方案:

  • 使用
    .values()
  • 使用
    .map()
    转换为
    id
    s的数组
  • 使用
    \uuu0.at()
    获取值
  • const{values,flatte,compact,partialOK:pr,map,partial,at}=;
    const fn=价格=>流量([
    价值观
    压平
    契约
    pr(地图,“id”),
    部分(按价格计算)
    ])
    常数价格={
    i_1:‘成本i_1’,
    i_2:“成本i_2”,
    i_3:“成本i_3”,
    i_4:‘成本i_4’,
    b_1:“成本b_1”,
    };
    常量特征={
    改进:[
    {id:'i_1'},
    {id:'i_2'},
    {id:'i_3'},
    {id:'i_4'},
    ],
    建筑:{
    id:“b_1”
    },
    };
    const result=fn(价格)(特征);
    控制台日志(结果)
    
    Lodash

    下面是一个使用
    .flow()
    的解决方案:

  • 使用
    .values()
  • 使用
    .map()
    转换为
    id
    s的数组
  • 使用
    \uuu0.at()
    获取值
  • const{values,flatte,compact,partialOK:pr,map,partial,at}=;
    const fn=价格=>流量([
    价值观
    压平
    契约
    pr(地图,“id”),
    部分(按价格计算)
    ])
    常数价格={
    i_1:‘成本i_1’,
    i_2:“成本i_2”,
    i_3:“成本i_3”,
    i_4:‘成本i_4’,
    b_1:“成本b_1”,
    };
    常量特征={
    改进:[
    {id:'i_1'},
    {id:'i_2'},
    {id:'i_3'},
    {id:'i_4'},
    ],
    建筑:{
    id:“b_1”
    },
    };
    const result=fn(价格)(特征);
    控制台日志(结果)
    
    以下是我使用Ramda的建议

    我建议将问题分解为更小的函数:

  • 获取所有改进的价格标识:
    getImprovementIds
  • 获取建筑的价格标识:
    getBuildingId
  • 获取所有内容的价格ID:
    getpriceID
  • 获取给定价格id的价格:
    getPrice
  • 示例

    getImprovementIds(features); //=> ['id_1', 'id_2', 'id_3']
    getBuildingIds(features);    //=> ['id_5']
    getPriceIds(features);       //=> ['id_1', 'id_2', 'id_3', 'id_5']
    getPrice(prices, 'id_2');    //=> 20
    getPrice(prices, 'foo');     //=> 0
    
    一旦有了价格ID列表,就可以很容易地将该列表转换为价格列表:

    map(getPrice(prices), ['id_1', 'id_2', 'id_3', 'id_5']); //=> [10, 20, 0, 50]
    
    完整示例

    const{propOr,ifElse,hasPath,path,always,compose,sum,map,flip,converge,of,concat}=R;
    常量特征={
    改进:['id_1'、'id_2'、'id_3'],
    建筑:{
    id:'id_5'
    }
    };
    常数价格={
    id_1:10,
    同上2:20,
    id_5:50
    };
    /**
    *获取features对象并返回所有改进的price id。
    *@param{object}特征
    *@return{array}id数组
    */
    const getImprovementIds=比例([],“改进”);
    /**
    *获取要素对象并返回建筑的价格id(如果有)
    *@param{object}特征
    *@return{array}id数组
    */
    常量getBuildingId=
    ifElse(hasPath(['building','id']),
    组成(of,path(['building',id']),
    总是([]);
    /**
    *获取features对象并返回所有改进和建筑(如果有)的所有price id
    *@param{object}特征
    *@return{array}id数组
    */
    const getPriceIds=converge(concat[getImprovementIds,getBuildingId]);
    /**
    *获取prices对象和price id并返回相应的价格
    *
    *@example
    *getPrice(prices,'id_2');//=>20
    *
    *@param{object}价格
    *@param{string}id
    *@return{number}
    */
    const getPrice=flip(比例(0));
    const getPriceList=(价格、功能)=>
    地图(getPrice(prices)、getpriceid(features));
    console.log(
    getPriceList(价格、功能)
    )

    以下是我使用Ramda的建议

    我建议将问题分解为更小的函数:

  • 获取所有改进的价格标识:
    getImprovementIds
  • 获取建筑的价格标识:
    getBuildingId
  • 获取所有内容的价格ID:
    getpriceID
  • 获取给定价格id的价格:
    getPrice
  • 示例

    getImprovementIds(features); //=> ['id_1', 'id_2', 'id_3']
    getBuildingIds(features);    //=> ['id_5']
    getPriceIds(features);       //=> ['id_1', 'id_2', 'id_3', 'id_5']
    getPrice(prices, 'id_2');    //=> 20
    getPrice(prices, 'foo');     //=> 0
    
    一旦有了价格ID列表,就可以很容易地将该列表转换为价格列表:

    map(getPrice(prices), ['id_1', 'id_2', 'id_3', 'id_5']); //=> [10, 20, 0, 50]
    
    完整示例

    const{propOr,ifElse,hasPath,path,always,compose,sum,map,flip,converge,of,concat}=R;
    常量特征={
    改进:['id_1'、'id_2'、'id_3'],
    建筑:{
    id:'id_5'
    }
    };
    常数价格={
    id_1:10,
    同上2:20,
    id_5:50
    };
    /**
    *获取features对象并返回所有改进的price id。
    *@param{object}特征
    *@return{array}id数组
    */
    const getImprovementIds=比例([],“改进”);
    /**
    *获取要素对象并返回建筑的价格id(如果有)
    *@param{object}特征
    *