什么是从嵌套的javascript对象中删除属性的最佳方法?

时间:2013-01-15 18:26:33

标签: javascript json recursion javascript-objects

我有一个树对象如下,我试图删除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: []
                    }]
                }]
            }]
        }]
    }]
}]

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

这是使用 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

的作者

答案 3 :(得分:0)

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

'operator-linebreak': ['error', 'before']
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} 属性,当它为空时跳过它,当它不是时重复出现。

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