【问题标题】:Whats the best way to remove a property from nested javascript Object?从嵌套的 javascript 对象中删除属性的最佳方法是什么?
【发布时间】:2012-12-29 22:37:03
【问题描述】:

我有一个如下的树对象,如果它是空的,我正在尝试删除 items 数组属性。我不确定执行此操作的最佳方法?

我正在考虑循环访问密钥,检查属性,然后使用 delete myJSONObject[prop] 删除...欢迎任何想法/想法?

[{
    text: "TreeRoot",
    items: [{
        text: "Subgroup1",
        items: []
    }, {
        text: "Subgroup2",
        items: []
    }, {
        text: "Subgroup3",
        items: [],
        items: [{
            text: "subgroup5",
            items: [{
                text: "subgroup6",
                items: [{
                    text: "subgroup7",
                    items: [{
                        text: "subgroup8",
                        items: []
                    }]
                }]
            }]
        }]
    }]
}]

【问题讨论】:

标签: javascript json recursion javascript-objects


【解决方案1】:

您可以使用递归算法,在每一步删除 items 数组并返回,或递归处理数组的每个单独对象。

我也会尝试在服务器端执行此操作。它将节省大量复杂性、内存和处理时间。通常有一些方法可以从 JSON 编码的字符串中“排除”空数组。

【讨论】:

    【解决方案2】:

    这应该可以完成工作(ES5):

    function removeEmpty(obj) {
      Object.keys(obj).forEach(function(key) {
        (key === 'items' && obj[key].length === 0) && delete obj[key] ||
        (obj[key] && typeof obj[key] === 'object') && removeEmpty(obj[key])
      });
      return obj;
    };
    

    JSBIN

    ES6 中相同:

    const removeEmpty = (obj) => {
      Object.keys(obj).forEach(key =>
        (key === 'items' && obj[key].length === 0) && delete obj[key] ||
        (obj[key] && typeof obj[key] === 'object') && removeEmpty(obj[key])
      );
      return obj;
    };
    

    JSBIN

    【讨论】:

      【解决方案3】:

      这是使用object-scan的解决方案

      // const objectScan = require('object-scan');
      
      const data = [{ text: 'TreeRoot', items: [{ text: 'Subgroup1', items: [] }, { text: 'Subgroup2', items: [] }, { text: 'Subgroup3', items: [{ text: 'subgroup5', items: [{ text: 'subgroup6', items: [{ text: 'subgroup7', items: [{ text: 'subgroup8', items: [] }] }] }] }] }] }];
      
      const modify = (obj) => objectScan(['**.items'], {
        rtn: 'count',
        filterFn: ({ value, parent, property }) => {
          if (Array.isArray(value) && value.length === 0) {
            delete parent[property];
            return true;
          }
          return false;
        }
      })(obj);
      
      console.log(modify(data)); // returns number of deletions
      // => 3
      console.log(data);
      // => [ { text: 'TreeRoot', items: [ { text: 'Subgroup1' }, { text: 'Subgroup2' }, { text: 'Subgroup3', items: [ { text: 'subgroup5', items: [ { text: 'subgroup6', items: [ { text: 'subgroup7', items: [ { text: 'subgroup8' } ] } ] } ] } ] } ] } ]
      .as-console-wrapper {max-height: 100% !important; top: 0}
      <script src="https://bundle.run/object-scan@13.7.1"></script>

      免责声明:我是object-scan的作者

      【讨论】:

        【解决方案4】:

        这个老问题已经被提出来了,我认为现代 JS 与递归配合得很好,可以产生一个简单的答案,以不可变的方式做到这一点:

        const removeEmptyItems = (xs) =>
           xs .map (({items = [], ... rest}) => ({
            ... rest, 
            ... (items .length ? {items: removeEmptyItems(items)} : {})
          }))
        
        const tree = [{text: "TreeRoot", items: [{text: "Subgroup1", items: []}, {text: "Subgroup2", items: []}, {text: "Subgroup3",items: [{text: "subgroup5", items: [{text: "subgroup6", items: [{text: "subgroup7", items: [{text: "subgroup8", items: []}]}]}]}]}]}]
        
        console .log (removeEmptyItems (tree))
        .as-console-wrapper {max-height: 100% !important; top: 0}

        这个函数只是简单地映射数组,保留每个对象的其余部分,并为其items 属性,当它为空时跳过它,当它不是空时重复。

        我不得不说,当第一次问这个问题时,这个答案看起来很陌生!现在它只是普通的JS!

        【讨论】:

          猜你喜欢
          • 2020-08-10
          • 1970-01-01
          • 1970-01-01
          • 2020-05-26
          • 1970-01-01
          • 1970-01-01
          • 2023-03-27
          • 1970-01-01
          • 2018-02-19
          相关资源
          最近更新 更多