根据相等对象的数量,消除相等对象并将最里面的 属性 递增 1

Eliminate equal objects and increment the innermost property by 1, based on the number of equal objects

我有以下代码消除数组中的相等对象,并将最里面的 属性 增加到相等对象的数量:

let SUPER = [{
    "NAME1": {
      "12": {
        "10": 1
      }
    }
  }, {
    "NAME1": {
      "12": {
        "10": 1
      }
    }
  }, {
    "NAME1": {
      "12": {
        "10": 1
      }
    }
  }, {
    "NAME1": {
      "12": {
        "10": 1
      }
    }
  }, {
    "NAME1": {
      "12": {
        "11": 1
      }
    }
  }],
  FINAL = [];

for (let _super of SUPER) {
  _super = JSON.stringify(_super);
  let ii = 1,
    ll = SUPER.length,
    number = 1;

  for (ii; ii < ll; ii++) {
    let current = JSON.stringify(SUPER[ii]);
    if (_super === current) {
      SUPER.splice(ii, 1);
      ii--;
      number++;
    }
  }

  if (number) {
    FINAL.push(function clone(destination, source) {
      destination = destination || {};
      for (var prop in source) {
        typeof source[prop] === 'object' && source[prop] !== null && source[prop] ? destination[prop] = clone({}, source[prop]) : destination[prop] = number;
      }
      return destination;
    }({}, JSON.parse(_super)));
  }
}

document.body.innerHTML = JSON.stringify(FINAL, null, 4);

如果没有两个或更多对象时的错误结果,并且几乎可以正常工作。结果应该是:

[{
    "NAME1": {
      "12": {
        "10": 4
      }
    }
  }, {
    "NAME1": {
      "12": {
        "11": 1
      }
    }
  }]

不是:

[{
    "NAME1": {
      "12": {
        "10": 4
      }
    }
  }, {
    "NAME1": {
      "12": {
        "11": 2
      }
    }
  }]

知道为什么吗?

给出的数据是示例数据。我不知道所有对象的实际属性。

问题:

  • 它在除第一个迭代之外的所有迭代中都加 1
  • 在 SUPER 丢失物品时使用 "for (let _super of SUPER) {"

我测试了更多 'unique' 个元素。如果您 运行 下面的代码,您将看到正确的结果。

var SUPER = [
    { "NAME1": { "12": { "21": 1 } } }, 
 { "NAME1": { "12": { "21": 1 } } }, 
 { "NAME1": { "12": { "10": 1 } } }, 
 { "NAME1": { "12": { "10": 1 } } }, 
 { "NAME1": { "12": { "10": 1 } } }, 
 { "NAME1": { "12": { "10": 1 } } }, 
 { "NAME1": { "12": { "10": 1 } } },
 { "NAME1": { "12": { "12": 1 } } }, 
 { "NAME1": { "12": { "11": 1 } } }, 
 { "NAME1": { "12": { "11": 1 } } }],
 FINAL = [];

var firstPass = true;

for (var i = 0; i < SUPER.length; i++) {
  _super = JSON.stringify(SUPER[i]);
  let ii = 1,
    ll = SUPER.length,
    number = 1;

  for (ii; ii < ll; ii++) {
    let current = JSON.stringify(SUPER[ii]);
    if (_super === current) {
      SUPER.splice(ii, 1);
      ii--;
      number++;
    }
  }

  if (number) {
    FINAL.push(function clone(destination, source) {
      destination = destination || {};
      for (var prop in source) {
        typeof source[prop] === 'object' && source[prop] !== null && source[prop] ? destination[prop] = clone({}, source[prop]) : (firstPass) ? destination[prop] = number : destination[prop] = number -1;
      }
      firstPass = false;
      return destination;
    }({}, JSON.parse(_super)));
  }
 
  if (SUPER.length > 0 && SUPER.length <= i) {
     i = 0;
  }
}

document.body.innerHTML = JSON.stringify(FINAL, null, 4);

输出:

[ { "NAME1": { "12": { "21": 2 } } }, { "NAME1": { "12": { "10": 5 } } }, { "NAME1": { "12": { "11": 2 } } }, { "NAME1": { "12": { "12": 1 } } } ]

有什么新鲜事? (与您的代码相比)

  • firstPass 声明为真
  • 从 "typeof source[prop] === 'object' && source[prop] !== null && source[prop] ? destination[prop] = clone({}, source[prop]) : (firstPass) ? destination[prop] = number : destination[prop] = number -1;"
  • 处的数字减 1
  • firstPass 设置为 false
  • 'for' 使用索引 i 而不是让 JS 自己遍历 SUPER(因为我们从 SUPER 中删除了元素)
  • 如果我 > SUPER.length
  • ,则将 'i' 重置为零

注意:您可以通过多种不同的方式修复它,这只是其中一种方式;)

ps:尽管代码可以正常工作,但我仍然不知道 "number" 问题的根本原因 =/ 所以,我考虑“(firstPass) ? destination[prop] = number : destination[prop] = number - 1" 是一种解决方法,而不是真正的解决方法。

您可以先生成所有键,查找是否使用该路径插入元素,如果没有则创建一个条目。之后,在对象中构建路径,最后将值添加到最内部对象。

let SUPER5 = [{ "NAME1": { "12": { "10": 1 } } }, { "NAME1": { "12": { "10": 1 } } }, { "NAME1": { "12": { "10": 1 } } }, { "NAME1": { "12": { "10": 1 } } }, { "NAME1": { "12": { "11": 1 } } }],
    SUPER10 = [{ "NAME1": { "12": { "21": 1 } } }, { "NAME1": { "12": { "21": 1 } } }, { "NAME1": { "12": { "10": 1 } } }, { "NAME1": { "12": { "10": 1 } } }, { "NAME1": { "12": { "10": 1 } } }, { "NAME1": { "12": { "10": 1 } } }, { "NAME1": { "12": { "10": 1 } } }, { "NAME1": { "12": { "12": 1 } } }, { "NAME1": { "12": { "11": 1 } } }, { "NAME1": { "12": { "11": 1 } } }],
    getGrouped = data => {
        var r = [],
            getKey = o => Object.keys(o)[0];
        data.forEach(function (a) {
            var o = a,
                t = {},
                k = getKey(a),
                keys = [k],
                jointKey;

            while (typeof o[k] === 'object') {
                o = o[k];
                k = getKey(o);
                keys.push(k);
            }
            jointKey = keys.join('|');
            if (!this[jointKey]) {
                this[jointKey] = t;
                r.push(t);
            }
            keys.pop();
            t = keys.reduce((r, a) => r[a] = r[a] || {}, this[jointKey]);
            t[k] = (t[k] || 0) + o[k];
        }, Object.create(null));
        return r;
    };

document.write('<pre>' + JSON.stringify(getGrouped(SUPER5), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(getGrouped(SUPER10), 0, 4) + '</pre>');