如何在使用递归清除函数时从数组中删除空实例?

时间:2019-02-12 14:56:49

标签: javascript arrays json postman

提供一些背景信息:通过使用Postman(REST api工具),我们将XML与模板进行比较,方法是将XML转换为JSON,并将它们作为Javascript对象进行比较。比较可以处理值中的通配符,并且将仅返回差异而返回新的JS对象(或JSON)。如果没有差异,我会收到一个空对象,它是正确的状态。在某些情况下,会返回空值或对象,我们会通过干净的步骤将其从对象中删除。

clean function的外观如下:

Utils = {
  clean: function(object) {
    Object
        .entries(object)
        .forEach(([k, v]) => {
            if (v && typeof v === 'object') 
                Utils.clean(v);
            if (v && typeof v === 'object' && !Object.keys(v).length || v === null || v === undefined) 
                Array.isArray(object) ? object.splice(k, 1) :  delete object[k]; 
        });
    return object;
  }
}

这在大多数情况下都可以正常工作,除非由于object.spliceforeach as pointed out here的组合而使数组具有多个相同的空对象。

通常,我会使用过滤器功能,使用lodash中的_.pickBy或向后遍历数组,但是由于clean函数的布局,我不知道该怎么做

您能帮我指出从阵列中正确删除多个空项目和对象时需要做什么。

现实生活中的测试用例:

var x = {"Document":{"CstmrDrctDbtInitn":{"GrpHdr":{},"PmtInf":{"DrctDbtTxInf":[{"PmtId":{}},{"PmtId":{}},{"PmtId":{}},{"PmtId":{}},{"PmtId":{}}]}}}};
console.log(JSON.stringify(Utils.clean(x)));
// returns {"Document":{"CstmrDrctDbtInitn":{"PmtInf":{"DrctDbtTxInf":[{},{}]}}}}
// desired result: {}

其他测试用例:

console.log(JSON.stringify(Utils.clean({"a": [null,null,"b","c",{},{},{},{}]})));
// returns {"a":[null,"c",{},{},{}]} 
// desired: {"a":["b", "c"]}

console.log(JSON.stringify(Utils.clean({"a": [null,null,"b","c",{"d": {}},{}]})));
// returns {"a":[null,"c",{},{}]} 
// desired: {"a":["b", "c"]}

console.log(JSON.stringify(Utils.clean({ "a" : [null,null,{"d": {}, "e": [null, {}]},{}]})));
// returns {"a":[null,{}]} 
// desired: {}

1 个答案:

答案 0 :(得分:1)

试一下,这是一个有效的示例:https://jsfiddle.net/3rno4L7d/

实用程序对象(带有额外的帮助程序)

const Utils = {
  doDelete: function(val) {
    return !Boolean(val) ||
      Utils.isEmptyObj(val) ||
      Utils.isEmptyArray(val);
  },
  isEmptyArray: function(val) {
    return Array.isArray(val) && val.length === 0;
  },
  isEmptyObj: function(obj) {
    return Object.keys(obj).length === 0 &&
      obj.constructor === Object;
  },
  hasKeys: function(obj) {
    return Object.keys(obj).length > 0;
  },
  clean: function(object) {
    Object
      .keys(object)
      .forEach(key => {
        const val = object[key];

        // If dealing with an object, clean it.
        if (val && typeof val === 'object') {
            Utils.clean(val);
        }

        // If deleteable, delete and return
        if (Utils.doDelete(val)) {
          delete object[key];
          return object;
        }

        // If array, loop over entries
        if (Array.isArray(val)) {
          let i = val.length;

          // While lets us delete from the array without affecting the loop.
          while (i--) {
            let entry = val[i];
            // If deleteable, delete from the array
            if (Utils.doDelete(entry)) {
              val.splice(i, 1)
            } else if (Utils.hasKeys(entry)) {
              // If an object, clean it
              entry = Utils.clean(entry);
              // Check to see if cleaned object is deleteable
              if (Utils.doDelete(entry)) {
                val.splice(i, 1)
              }
            }
          }
          // Once done with the array, check if deleteable
          if (Utils.doDelete(val)) {
            delete object[key];
          }
        }
      });
    return object;
  }
}

输出

console.log(JSON.stringify(Utils.clean({"a": [null,null,"b","c",{},{},{},{}]})));
// Returns {"a":["b","c"]}

console.log(JSON.stringify(Utils.clean({"a": [null,null,"b","c",{"d": {}},{}]})));
// Returns {"a":["b","c"]}

console.log(JSON.stringify(Utils.clean({ "a" : [null,null,{"d": {}, "e": [null, {}]},{}]})));
// Returns {}