【问题标题】:Remove object that have an empty array value删除具有空数组值的对象
【发布时间】:2021-11-17 09:57:16
【问题描述】:

所以我在json 文件中有一个对象,如下所示:

{
    "0": {
        "damage_type": "Scratch",
        "regions": []
    },
    "1": {
        "damage_type": "Dent",
        "regions": []
    },
    "2": {
        "damage_type": "Dent",
        "regions": [
            "front side",
            "front window"
        ]
    }
}

我想要完成的是删除具有空regions 的对象。像这样:

{
    "2": {
        "damage_type": "Dent",
        "regions": [
            "front side",
            "front window"
        ]
    }
}

我正在使用 for 循环,但仍然不成功:

jsonfile.readFile(theJsonFile, function (err, obj) {
    if (err) console.error(err)

    for (var i = 0; i <= Object.keys(obj).length - 1; i++) {
      if (obj[i].damage_type.length < 1) {
        delete obj[i]
      } 
    }
}

有什么想法吗?

【问题讨论】:

  • 您正在检查damage_type 的长度,而不是regions

标签: javascript node.js arrays json


【解决方案1】:

你可以通过key删除一个json节点

var json = { ... };
var key = "foo";
delete json[key]; // Removes json.foo from the dictionary.

【讨论】:

  • OP 似乎已经知道如何删除属性。 (另外,一个挑剔:不要将 JS 数据结构命名为 json,除非它实际上包含 JSON 字符串化的值。在您的情况下,您最好将其命名为 dataobjvalue、等)
【解决方案2】:

为什么您的代码不起作用?

您从每个节点错误地检查damage_type.length 的条件。您需要删除带有空regions 的节点。所以你必须检查regions.length

您的有效解决方案

const obj = { 
  "0": { "damage_type": "Scratch", "regions": [] },
  "1": { "damage_type": "Dent", "regions": [] },
  "2": { "damage_type": "Dent", "regions": [ "front side", "front window" ] }
};

for (var i = 0; i < Object.keys(obj).length; i++) {
  if (!obj[i].regions || obj[i].regions.length === 0) {
    delete obj[i]
  } 
}
console.log(obj);

此解决方案之所以有效,是因为对象的键与索引“0”、“1”和“2”相同。如果密钥是其他东西,这将不起作用。

更正的解决方案

使用Object.keys 获取密钥并删除正确的节点。

工作小提琴

const obj = { 
  "0": { "damage_type": "Scratch", "regions": [] },
  "1": { "damage_type": "Dent", "regions": [] },
  "2": { "damage_type": "Dent", "regions": [ "front side", "front window" ] }
};
const keys = Object.keys(obj);
for (var i = 0; i <= keys.length - 1; i++) {
  if (!obj[keys[i]].regions || obj[keys[i]].regions.length === 0) {
    delete obj[keys[i]]
  } 
}
console.log(obj);

通用解决方案

使用Object.entries获取键值组合

const obj = { 
  "0": { "damage_type": "Scratch", "regions": [] },
  "1": { "damage_type": "Dent", "regions": [] },
  "2": { "damage_type": "Dent", "regions": [ "front side", "front window" ] }
};
const entries = Object.entries(obj);
entries.forEach(([key, value]) => {
  if (!value.regions || value.regions.length === 0) {
    delete obj[key]
  }
})
console.log(obj);

【讨论】:

  • 您可能希望Object.entries(data) 使用实际的密钥。在您的示例中,很幸运,这些值的索引方式与原始对象的键相同。
  • 是的,Object.entries(data)Object.keys 可以解决问题,无论键的值如何。
  • 调用data[key] 两次仍然低于使用Object.entries() 同时获取键和值。此外,OP 似乎不需要检查 regions 属性是否存在。
  • @AtesGoral 同意 用Object.entries() 更新了答案。 OP 需要删除具有空区域的节点。所以regions键需要验证删除条件
【解决方案3】:

做出改变,试试这个

let json = {
    "0": {
        "damage_type": "Scratch",
        "regions": []
    },
    "1": {
        "damage_type": "Dent",
        "regions": []
    },
    "2": {
        "damage_type": "Dent",
        "regions": [
            "front side",
            "front window"
        ]
    }
};


function walk(obj) {
  for (var key in obj) {
     let length = Object.keys(obj[key].regions).length; // get the length
     if(length==0){
       delete obj[key];
       
     }
  }
 console.log(json);
}
walk(json);

输出

{ '2':
   { damage_type: 'Dent',
     regions: [ 'front side', 'front window' ]
 } 
}

【讨论】:

  • @hisam 如果这是您要找的,请点赞。
【解决方案4】:

调用解析后的值damages 而不是obj,您可以将所有条目作为键/值对抓取,对其进行迭代并通过其ID 删除无区域“损坏”:

Object.entries(damages).forEach(([id, damage]) => {
  if (!damage.regions.length) {
    delete damages[id];
  }
});

或者,您可以在不触及原始结构的情况下创建一个全新的结构:

const entries = Object.entries(damages);
const filteredEntries = entries.filter(([_, damage]) => damage.regions.length);
const filteredDamages = Object.fromEntries(filteredEntries);

【讨论】:

    【解决方案5】:

    在这种情况下,首先你需要一个数组。要将对象转换为数组,请使用条目entry

    let obj = {
        "0": {
            "damage_type": "Scratch",
            "regions": []
        },
        "1": {
            "damage_type": "Dent",
            "regions": []
        },
        "2": {
            "damage_type": "Dent",
            "regions": [
                "front side",
                "front window"
            ]
        }
    }
    

    转换数组:

    const myentry= Object.entries(obj);
    

    现在消除或过滤数组的最好方法是使用过滤器方法,然后获取另一个具有过滤器值的对象。

    Filter

    const myFiletrObj = myentry.filter(([_, obj]) => obj.regions.length).reduce(withObjectAssign, {})
    
    function withObjectAssign(object, [key, value]) {
      return Object.assign(object, {[key]: value})
    }
    

    这将为您提供过滤后的输出。

    【讨论】:

      猜你喜欢
      • 2017-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-07
      • 1970-01-01
      • 2019-03-29
      • 2017-08-21
      • 2015-12-24
      相关资源
      最近更新 更多