【问题标题】:Removing object properties with Lodash使用 Lodash 删除对象属性
【发布时间】:2017-03-12 19:14:52
【问题描述】:

我必须删除与我的模型不匹配的不需要的对象属性。如何使用 Lodash 实现它?

我的模型是:

var model = {
   fname: null,
   lname: null
}

在发送到服务器之前我的控制器输出将是:

var credentials = {
    fname: "xyz",
    lname: "abc",
    age: 23
}

我知道我可以使用

delete credentials.age

但是如果我有很多不需要的属性怎么办?我可以用 Lodash 实现它吗?

【问题讨论】:

    标签: javascript lodash


    【解决方案1】:

    您可以通过“允许列表”或“阻止列表”方式来处理它:

    // Block list
    // Remove the values you don't want
    var result = _.omit(credentials, ['age']);
    
    // Allow list
    // Only allow certain values
    var result = _.pick(credentials, ['fname', 'lname']);
    

    如果它是可重用的业务逻辑,你也可以将其分出来:

    // Partial out a "block list" version
    var clean = _.partial(_.omit, _, ['age']);
    
    // and later
    var result = clean(credentials);
    

    请注意,Lodash 5 将放弃对 omit 的支持

    没有 Lodash 也可以实现类似的方法:

    const transform = (obj, predicate) => {
        return Object.keys(obj).reduce((memo, key) => {
        if(predicate(obj[key], key)) {
            memo[key] = obj[key]
        }
        return memo
        }, {})
    }
    
    const omit = (obj, items) => transform(obj, (value, key) => !items.includes(key))
    
    const pick = (obj, items) => transform(obj, (value, key) => items.includes(key))
    
    // Partials
    // Lazy clean
    const cleanL = (obj) => omit(obj, ['age'])
    
    // Guarded clean
    const cleanG = (obj) => pick(obj, ['fname', 'lname'])
    
    
    // "App"
    const credentials = {
        fname:"xyz",
        lname:"abc",
        age:23
    }
    
    const omitted = omit(credentials, ['age'])
    const picked = pick(credentials, ['age'])
    const cleanedL = cleanL(credentials)
    const cleanedG = cleanG(credentials)
    

    【讨论】:

    • 这是正确的答案,因为删除的函数是 _.omit_.pick 指定你想要的(正好相反)
    • 正确 - 取决于您的一般方法和周围的业务逻辑 - 任何一个版本都可以根据您的要求工作
    • 对于您打错字的部分,它是_.partial(_.omit ...
    • 黑名单是这个问题的预期答案。应该是正确的答案
    【解决方案2】:

    使用_.keys()model获取属性列表,并使用_.pick()credentials提取属性到一个新对象:

    var model = {
       fname:null,
       lname:null
    };
    
    var credentials = {
        fname:"xyz",
        lname:"abc",
        age:23
    };
    
    var result = _.pick(credentials, _.keys(model));
    
    console.log(result);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script>

    如果不想使用 Lodash,可以使用Object.keys()Array.prototype.reduce()

    var model = {
       fname:null,
       lname:null
    };
    
    var credentials = {
        fname:"xyz",
        lname:"abc",
        age:23
    };
    
    var result = Object.keys(model).reduce(function(obj, key) {
      obj[key] = credentials[key];
      return obj;
    }, {});
    
    console.log(result);

    【讨论】:

      【解决方案3】:

      您可以使用 _.pick 轻松做到这一点:

      var model = {
        fname: null,
        lname: null
      };
      
      var credentials = {
        fname: 'abc',
        lname: 'xyz',
        age: 2
      };
      
      var result = _.pick(credentials, _.keys(model));
      
      
      console.log('result =', result);
      <script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"></script>

      但是你可以简单地使用纯 JavaScript(特别是如果你使用 ECMAScript 6),像这样:

      const model = {
        fname: null,
        lname: null
      };
      
      const credentials = {
        fname: 'abc',
        lname: 'xyz',
        age: 2
      };
      
      const newModel = {};
      
      Object.keys(model).forEach(key => newModel[key] = credentials[key]);
      
      console.log('newModel =', newModel);

      【讨论】:

        【解决方案4】:

        Lodash unset 适合删除一些不需要的键。

        const myObj = {
            keyOne: "hello",
            keyTwo: "world"
        }
        
        unset(myObj, "keyTwo");
        
        console.log(myObj); /// myObj = { keyOne: "hello" }

        【讨论】:

          【解决方案5】:

          在这里,我已将 omit() 用于您要删除的各个“密钥”...通过使用 Lodash 库:

          var credentials = [{
                  fname: "xyz",
                  lname: "abc",
                  age: 23
          }]
          
          let result = _.map(credentials, object => {
                                 return _.omit(object, ['fname', 'lname'])
                             })
          
          console.log('result', result)
          

          【讨论】:

          【解决方案6】:

          如果您的对象较少,您可以使用_.omit() 从 JSON 数组中发出密钥:

          _.forEach(data, (d) => {
              _.omit(d, ['keyToEmit1', 'keyToEmit2'])
          });
          

          如果你有更多的对象,你可以使用它的反面,即_.pick()

          _.forEach(data, (d) => {
              _.pick(d, ['keyToPick1', 'keyToPick2'])
          });
          

          【讨论】:

            【解决方案7】:

            要选择(或删除)满足给定条件的对象属性深度,您可以使用以下内容:

            function pickByDeep(object, condition, arraysToo=false) {
              return _.transform(object, (acc, val, key) => {
                if (_.isPlainObject(val) || arraysToo && _.isArray(val)) {
                  acc[key] = pickByDeep(val, condition, arraysToo);
                } else if (condition(val, key, object)) {
                  acc[key] = val;
                }
              });
            }
            

            https://codepen.io/aercolino/pen/MWgjyjm

            【讨论】:

              【解决方案8】:

              这是我用 Lodash 深度删除空属性的解决方案:

              const compactDeep = obj => {
                  const emptyFields = [];
              
                  function calculateEmpty(prefix, source) {
                      _.each(source, (val, key) => {
                         if (_.isObject(val) && !_.isEmpty(val)) {
                              calculateEmpty(`${prefix}${key}.`, val);
                          } else if ((!_.isBoolean(val) && !_.isNumber(val) && !val) || (_.isObject(val) && _.isEmpty(val))) {
                              emptyFields.push(`${prefix}${key}`);
                          }
                      });
                  }
              
                  calculateEmpty('', obj);
              
                  return _.omit(obj, emptyFields);
              };
              

              【讨论】:

              • 这是什么想法?你的解决方案有什么作用?
              • -1;这对于解决提问者给出的示例问题以及从对象中删除属性的一般问题都没有用;这是一个奇怪的任意问题的解决方案,这个问题不是被问到的,也没有在这个答案中详细说明。它也不是幂等的(compactDeep({a: {b: []}}) 给出了与compactDeep(compactDeep({a: {b: []}})) 不同的结果,这感觉像是一个错误,尽管人们不能真正客观地说出来,因为它没有说明这是什么意思。
              【解决方案9】:

              对象数组

              model = _.filter(model, a => {
                        if (!a.age) { return a }
                      })
              

              【讨论】:

              • 欢迎来到 Stack Overflow,感谢您提供答案。您能否编辑您的答案以包括对您的代码的解释?这将帮助未来的读者更好地理解正在发生的事情,尤其是那些不熟悉该语言并努力理解这些概念的社区成员。当五年前的答案已经得到社区的验证时,这一点尤其重要,迄今为止已有 178 次投票。在什么条件下你的方法可能更受欢迎?您是否在利用新功能?
              【解决方案10】:

              递归删除路径。

              我只需要类似的东西,不只是删除键,而是通过路径递归地删除键。

              我想我会分享。

              简单易读的例子,没有依赖关系

              /**
               * Removes path from an object recursively.
               * A full path to the key is not required.
               * The original object is not modified.
               *
               * Example:
               *   const original = { a: { b: { c: 'value' } }, c: 'value'  }
               *
               *   omitPathRecursively(original, 'a') // outputs: { c: 'value' }
               *   omitPathRecursively(original, 'c') // outputs: { a: { b: {} } }
               *   omitPathRecursively(original, 'b.c') // { a: { b: {} }, c: 'value' }
               */
              export const omitPathRecursively = (original, path, depth = 1) => {
                const segments = path.split('.')
                const final = depth === segments.length
              
                return JSON.parse(
                  JSON.stringify(original, (key, value) => {
                    const match = key === segments[depth - 1]
              
                    if (!match) return value
                    if (!final) return omitPathRecursively(value, path, depth + 1)
                    return undefined
                  })
                )
              }
              

              工作示例:https://jsfiddle.net/webbertakken/60thvguc/1/

              【讨论】:

                猜你喜欢
                • 2016-01-03
                • 2018-05-27
                • 2021-06-28
                • 1970-01-01
                • 1970-01-01
                • 2014-07-18
                • 1970-01-01
                • 1970-01-01
                • 2018-07-31
                相关资源
                最近更新 更多