如何在JavaScript中深度嵌套的对象成员上使用Ramda的omit()函数

时间:2018-09-29 13:53:31

标签: javascript eval javascript-objects ramda.js

我遇到一种情况,我想在展平并导出为CSV之前删除对象树的任何部分。 Ramda是我在JS中选择FP的选择库,但我注意到R.omit()函数仅在目标对象深一层起作用。我该如何做才能做到以下几点?

const R = require('ramda');

const obj = {
    id: 1,
    name: 'me',
    audience_sizes: {
        fb: 500,
        dfp: 2000,
        apn: 1800
    }
};

console.log(JSON.stringify(R.omit(['id', 'audience_sizes.fb'], obj)));

我希望得到以下结果:

{"name":"me","audience_sizes":{"dfp":2000, "apn": 1800}}

4 个答案:

答案 0 :(得分:2)

我认为Lenses是一种更实用的方法。

R.over(R.lensProp('audience_sizes'), R.omit(['fb']), R.omit(['id'], obj));

答案 1 :(得分:1)

DissocPath看起来像您要找的东西。使用它或镜头进行更复杂的深度更新。

答案 2 :(得分:0)

我通过使用以下功能解决了这个问题。在下面的解决方案中,如何避免使用eval()处理对象成员的深层引用?基本上,我正在寻找一种更好的方法来实现此功能:

//This is a supplemental function to Ramda's omit(), which allows deep key referencing
export const omitDeep = R.curry((keys, obj) => {
  if(!keys || keys.length===0) return obj;
  let newObj = Object.assign({}, obj);
  keys.forEach( key => {
      let keyParts = key.split('.');
      if(keyParts.length < 2) {
          newObj = R.omit(keyParts, newObj);
          return;
      }
      let target = newObj[keyParts[0]];
      let objString = `newObj.${keyParts[0]}`;
      for(let i=1; i < keyParts.length - 1; i++){
          target = target[keyParts[i]];
          objString += `.${keyParts[0]}`;
      }
      const subj = keyParts[keyParts.length-1];
      target = R.omit([subj], target);
      eval(`${objString} = target`);
   });
   return newObj;
});

谢谢!

答案 3 :(得分:0)

根据更多经验丰富的Ramda用户的建议,我将omitDeep函数重构如下:

//This is a supplemental function to Ramda's omit(), which allows deep key referencing
export const omitDeep = R.curry((keys, obj) => {
  if(!keys || keys.length===0) return obj;
  let newObj = R.clone(obj);
  keys.forEach( key => {
      let keyParts = key.split('.');
      newObj = R.dissocPath(keyParts, newObj);
  });    
  return newObj;
});

感谢@Buggy和@Ebuall!