【问题标题】:Cleaning out bad JSON data from object?从对象中清除错误的 JSON 数据?
【发布时间】:2015-07-23 04:05:50
【问题描述】:

我正在从服务中检索建筑地理位置数据,但在某些情况下,某些数据会缺少属性。

良好的数据

[{
    "ModifiedOn": "2015-04-29 11:17:28.0",
    "BuildingName": "Wintefell",
    "Latitude": "52.900619",
    "Longitude": "-1.434602",
    "Region": "The North",
}, {
    "ModifiedOn": "2015-04-29 11:17:28.0",
    "BuildingName": "Water Gardens",
    "Latitude": "51.818051",
    "Longitude": "-.354871",
    "Region": "Dorne"
}]

不良数据

缺少区域或建筑物名称

{
    "ModifiedOn": "2015-04-29 11:17:28.0",
    "BuildingName": "Kings Landing",
    "Latitude": "23.818051",
    "Longitude": "-.154871",
}

发出 AJAX 请求后,我将 JSON 响应存储在一个名为 _regionAndBuildings

的对象中

我想从中清除任何不良数据,所以我尝试了以下代码

console.log("Starting size of building data : " + _regionAndBuildings.length);
//clean json by setting object to undefined
for (var i = 0; i < _regionAndBuildings.length; i++) {
    if (_regionAndBuildings[i].BuildingName === undefined && _regionAndBuildings[i].Region === undefined) {
        console.log("Deleting");
        delete _regionAndBuildings[i];
    }
}
console.log("Ending size of building data after cleaning : " + _regionAndBuildings.length);

输出

起始尺寸:209

删除 x 17

结束大小:209

为什么这段代码没有删除我的 JSON 对象中的坏元素?

【问题讨论】:

  • 尝试使用array.splice 而不是删除。

标签: javascript arrays json data-cleaning


【解决方案1】:

您的代码中有两个问题。

  1. 根据问题

    缺少区域或建筑物名称

    您要删除的元素是 Region 或 Building Name 缺失。但条件并没有反映出这一点

    if (_regionAndBuildings[i].BuildingName === undefined && 
        _regionAndBuildings[i].Region === undefined)
    

    由于你使用了&amp;&amp;操作符,只有当两个表达式都满足时,if条件里面的代码才会被执行。所以,你需要用逻辑或运算符||来改变它,像这样

    if (_regionAndBuildings[i].BuildingName === undefined ||
        _regionAndBuildings[i].Region === undefined)
    
  2. 当你对数组使用delete 运算符时,数组中的元素将被删除,但索引将指向任何内容。这意味着数组的长度不会改变。在this section了解更多信息

    相反,您可以使用Array.prototype.splice,像这样

    _regionAndBuildings.splice(i, 1);
    

但是,我更喜欢使用Array.prototype.filter 重构数组而不包含您不想要的元素,就像这样

var filteredBuildings = _regionAndBuildings.filter(function (currentObject) {
    return currentObject.hasOwnProperty("BuildingName") &&
        currentObject.hasOwnProperty("Region");
});

现在,传递的函数将与数组中的所有项目一起运行,并且只有当函数返回 true 时,该对象才会包含在过滤结果中。因此,如果对象同时具有BuildingNameRegion 属性,那么只有它才会包含在结果中。


注意:我更喜欢使用Object.hasOwnProperty来检查对象中是否存在属性,而不是将值与undefined进行比较,因为如果属性的值实际上是undefined ,那么我们就无法区分不存在的属性和值为undefined的属性。

【讨论】:

  • 您对检查每个对象的大小有何看法?如果我知道好的数据有 6 个属性。因此,如果属性大小小于 6。
  • @loosebruce 但是你不会知道缺少哪些属性,对吧?
【解决方案2】:

你能试试吗:

if (typeof _regionAndBuildings[i].BuildingName === "undefined" 
       && typeof _regionAndBuildings[i].Region === "undefined")
            {
                console.log("Deleting");
               _regionAndBuildings.splice(i, 1);
}

【讨论】:

    【解决方案3】:

    第一个原因 - 你在那里使用&amp;&amp; 而不是||

    _regionAndBuildings[i].BuildingName === undefined && _regionAndBuildings[i].Region === undefined
    

    但你说:

    不良数据

    缺少区域建筑物名称

    第二个原因 - 当您从数组中删除 delete 的元素时,您会得到一个间隙 undefined

    [<elem>, undefined, <elem>]
    

    删除了 Elem,但长度将保持不变。 您可以稍后通过filter 删除undefined

    var newArray = yourArray.filter(function(item) { return item});
    

    但最好的方法是使用slice 而不是delete

    _regionAndBuildings.splice(i, 1);
    

    【讨论】:

    • 你也可以使用 if (!(arr[i].BuildingName &amp;&amp; !arr[i].Region)) 而不是 ||
    【解决方案4】:

    你可以反过来做,filter 数组以获得好的值:

    var goodRegionAndBuildings = _regionAndBuildings.filter(function(item) {
        // assumes not-empty strings are good
        // everything else is bad
        return (
            item.ModifiedOn !== "" &&
            item.BuildingName !== "" &&
            item.Latitude !== "" &&
            item.Longitude !== "" &&
            item.Region !== ""
        );
    });
    

    【讨论】:

    • 如果说 95% 的数据是好的而 5% 的数据是坏的,那么性能的权衡是什么?
    【解决方案5】:

    在你给出的例子中

    {
        "ModifiedOn": "2015-04-29 11:17:28.0",
        "BuildingName": "Kings Landing",
        "Latitude": "23.818051",
        "Longitude": "-.154871",
    }  
    

    属性BuildingNameRegion 丢失。使用hasOwnProperty 而不是_regionAndBuildings[i].BuildingName === undefined 更合适

    for (var i = 0; i < _regionAndBuildings.length; i++){
        if (!(_regionAndBuildings[i].hasOwnProperty('BuildingName')) && !(_regionAndBuildings[i].hasOwnProperty('Region'))) {
            console.log("Deleting");
            _regionAndBuildings.splice(i, 1);
         }
    }  
    

    DEMO

    【讨论】:

      猜你喜欢
      • 2012-02-29
      • 2015-03-13
      • 2019-12-03
      • 2013-02-03
      • 2016-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-25
      相关资源
      最近更新 更多