简体   繁体   中英

Javascript Iterate an array, count the number of times each element appears and push it to an object

I'm trying to implement the following code:

var data = [];
var devicesObj = {};
var devices = clients.map(function(k) {
    return k.os;
});

devices.sort();

var current = null;
var cnt = 0;

for (var i = 0; i <= devices.length; i++) {
    if (devices[i] !== current) {
        if (cnt > 0) {
            devicesObj.label = current;
            devicesObj.value = cnt;
        }
            data.push(devicesObj);
            current = devices[i];
            cnt = 1;
        } else {
            cnt++;
        }

}

The idea is to try to iterate through the devices array, get the name of each element and count the times it is repeated inside the array. Then assign the current element name to an object under the key label and the total count the value key. And finally push the new object to a new array.

The structure of array that maps to the devices variable:

{ _id: 58d095c272b61889a6688922,
   id: 'k65f508',
   os: 'Apple iPhone',
   mac: 'f0:24:75' },
{ _id: 58d095c272b61889a6688923,
   id: 'k00e8fc',
   os: 'Android',
   mac: '08:ec:a9' },
{ _id: 58d095c272b61889a6688924,
   id: 'k65f637',
   os: 'Android',
   mac: 'c0:bd:d1' },
{ _id: 58d095c272b61889a6688925,
   id: 'k00b0ec',
   os: 'Windows',
   mac: '74:e2:8c' },
{ _id: 58d095c272b61889a6688926,
   id: 'k00328a',
   os: 'Android',
   mac: 'd0:87:e2' },
{ _id: 58d095c272b61889a6688927,
   id: 'k0006b1',
   os: 'Apple iPhone',
   mac: '9c:d3:5b' }

After executing the code I get the following result:

[
  {
    "label": "Apple iPhone",
    "value": 2
  },
  {
    "label": "Apple iPhone",
    "value": 2
  },
  {
    "label": "Apple iPhone",
    "value": 2
  },
  {
    "label": "Apple iPhone",
    "value": 2
  },
  {
    "label": "Apple iPhone",
    "value": 2
  },
  {
    "label": "Apple iPhone",
    "value": 2
  }
]

Please help!!

You're pushing the same object over and over. Try this:

for (var i = 0; i < devices.length; i++) {
    if (devices[i] !== current) {
        if (cnt > 0) {
            data.push({label: current, value: cnt});
        }
        current = devices[i];
        cnt = 0;
    }
    cnt++;
}
if (cnt > 0) {
    data.push({label: current, value: cnt});
}

There are a number of issues. One is that you're reusing the same object and that's why you wind up with all of the array elements having the same value.

The other is that the logic in your loop is faulty, will not correctly account for all of the ways the data could be configured, and keeps pushing values into the array when it shouldn't.

Yet another is that you're using <= in your loop condition when you should be using < .

Try this:

 var clients = getClients(); var devicesObj; var devices = clients.map(function(k) { return k.os; }); devices.sort(); var current = null; var data = []; for (var i = 0; i < devices.length; i++) { if (current !== devices[i]) { current = devices[i]; devicesObj = { label: current, value: 0 }; data.push(devicesObj); } devicesObj.value += 1; } console.log(data); // sample clients data function getClients() { return [{ _id: '58d095c272b61889a6688922', id: 'k65f508', os: 'Apple iPhone', mac: 'f0:24:75' }, { _id: '58d095c272b61889a6688923', id: 'k00e8fc', os: 'Android', mac: '08:ec:a9' }, { _id: '58d095c272b61889a6688924', id: 'k65f637', os: 'Android', mac: 'c0:bd:d1' }, { _id: '58d095c272b61889a6688925', id: 'k00b0ec', os: 'Windows', mac: '74:e2:8c' }, { _id: '58d095c272b61889a6688926', id: 'k00328a', os: 'Android', mac: 'd0:87:e2' }, { _id: '58d095c272b61889a6688927', id: 'k0006b1', os: 'Apple iPhone', mac: '9c:d3:5b' } ]; } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM