Confirm number of occurrences of a objects in array

爱⌒轻易说出口 提交于 2019-12-12 18:13:40

问题


I'm having a huge difficulty in creating a program to check the number of occurrences of objects in array based on rules set by me. If a particular object exists more then one, I count the number of occurrences.

Example input:

[
  '{"NAME1":{"12":{"10":1}}}',
  '{"NAME1":{"12":{"10":1}}}',
  '{"NAME1":{"12":{"10":1}}}'
]

Example output:

[
  '{"NAME1":{"12":{"10":3}}}'
]

WARNING: THIS IS A EXAMPLE.

So, how i'm doing:

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

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

  for (ii; ii < ll; ii++) {
    let current = JSON.stringify(SUPER[ii]);
    if (_super === current) {
      SUPER.splice(ii, 1);
      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);

So, i'm looping over the SUPER two times, one inside the other to test each object, and if i find equal strings, i increase the number by one and remove the object from the array, then i use this script to assign the number to the innermost property of the object:

  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)));
  }

But isn't working properly because of a conflict in this line:

    if (_super === current) {
      SUPER.splice(ii, 1);
      number++;
    }

I'm messing up the loop. Any ideas how to fix? I'm open to suggestions, i don't know if there is a better way to achieve this, i hope someone knows.

Thanks.


回答1:


Try writing your own equals function and find the occurences for those in the array.




回答2:


If you are the one to set the "dynamically" changing rules then to perform this job is very easy by an invention of two Object methods; namely Object.prototype.getNestedValue() and Object.prototype.setNestedValue(). Lets do it. Both methods take a number of arguments which are the object properties (if the argument is "string" type) or array indices(if the argument is "number" type). In addition to that, in the Object.setNestedValues() the very last argument is the value to be set. Just simple.

So here it goes like this;

Object.prototype.getNestedValue = function(...a) {
  return a.length > 1 ? (this[a[0]] !== void 0 && this[a[0]].getNestedValue(...a.slice(1))) : this[a[0]];
};
Object.prototype.setNestedValue = function(...a) {
  return a.length > 2 ? typeof this[a[0]] === "object" && this[a[0]] !== null ? this[a[0]].setNestedValue(...a.slice(1))
                                                                              : (this[a[0]] = typeof a[1] === "string" ? {} : new Array(a[1]),
                                                                                 this[a[0]].setNestedValue(...a.slice(1)))
                      : this[a[0]] = a[1];
};

var data = [
  '{"NAME1":{"12":{"10":1}}}',
  '{"NAME1":{"12":{"10":1}}}',
  '{"NAME1":{"12":{"10":1}}}'
],
   props = ["NAME1", "12", "10"], // this array is constructed dynamically !!
 reduced = [data.reduce((p,c) => {var v = p.getNestedValue(...props);
                                  p.setNestedValue(...props, !!v ? ++v : 1);
                                  return p;},{})];
console.log(JSON.stringify(reduced,null,2));



回答3:


When you splice the array, elements are shifted to left by 1 but the loop index continues to move forward not accounting for this shift. You can account for it by decrementing the current loop index by 1 each time you splice.

e.g: t = [1,2,3,4];

console.log(t[1]); // output: 2

//when you splice

t.splice(1,1);

// after splicing the array elements are shifted

console.log(t[1]); //output: 3

Working solution:

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

for (let i = 0; i < SUPER.length; i++) {
  let _super = JSON.stringify(SUPER[i]),
    ii = i + 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);

I have also initialized ii, number to 1 to reduce one iteration of inner loop.



来源:https://stackoverflow.com/questions/37397211/confirm-number-of-occurrences-of-a-objects-in-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!