tFranzoni
tFranzoni

Reputation: 17

How to group elements from an array into an object that meets certain criteria and push it to new array

I have the following array:

"devices": [
    {
      "_id": "HP Printer",
      "count": 1
    },
    {
      "_id": "55UA8990",
      "count": 1
    },
    {
      "_id": "Mac OS X 10.5",
      "count": 1
    },
    {
      "_id": "Nokia",
      "count": 4
    },
    {
      "_id": "Ubuntu Linux",
      "count": 3
    },
    {
      "_id": "LG handset",
      "count": 1
    },
    {
      "_id": "Samsung Home Audio/Video equipment",
      "count": 1
    },
    {
      "_id": "Generic Linux",
      "count": 1
    },
    {
      "_id": "Sony handset",
      "count": 1
    },
    {
      "_id": "Mac OS X 10.8",
      "count": 12
    },
    {
      "_id": "Linux Handheld",
      "count": 1
    },
    {
      "_id": "Symbian OS",
      "count": 15
    },
    {
      "_id": "RIM BlackBerry",
      "count": 28
    },
    {
      "_id": "Apple iPod",
      "count": 1
    },
    {
      "_id": "LG BL40",
      "count": 1
    },
    {
      "_id": "Slingbox",
      "count": 67
    },
    {
      "_id": "Windows XP",
      "count": 60
    },
    {
      "_id": "BlackBerry",
      "count": 51
    },
    {
      "_id": "Chrome OS",
      "count": 7
    },
    {
      "_id": "Eye-Fi Wireless Memory Card",
      "count": 6
    },
    {
      "_id": "Mac OS X 10.9",
      "count": 62
    },
    {
      "_id": "Mac OS X 10.10",
      "count": 215
    },
    {
      "_id": "Windows Vista",
      "count": 4
    },
    {
      "_id": "Windows Mobile OS",
      "count": 213
    },
    {
      "_id": "Windows 7/Vista",
      "count": 394
    },
    {
      "_id": "Mac OS X 10.11",
      "count": 303
    },
    {
      "_id": "Samsung TV",
      "count": 1
    },
    {
      "_id": "PlayStation Portable",
      "count": 1
    },
    {
      "_id": "Mac OS X",
      "count": 755
    },
    {
      "_id": "Windows 7",
      "count": 612
    },
    {
      "_id": "Apple iPad",
      "count": 2597
    },
    {
      "_id": "Ellipsis 8",
      "count": 193
    },
    {
      "_id": "Mac OS X 10.12",
      "count": 550
    },
    {
      "_id": "Nexus",
      "count": 4657
    },
    {
      "_id": "Windows 10",
      "count": 772
    },
    {
      "_id": "Windows 8",
      "count": 1191
    },
    {
      "_id": "Xbox 360",
      "count": 39
    },
    {
      "_id": "Mac OS X 10.6",
      "count": 5
    },
    {
      "_id": "Apple iPhone",
      "count": 41039
    },
    {
      "_id": "iOS",
      "count": 25725
    },
    {
      "_id": "Debian-based Linux",
      "count": 9
    },
    {
      "_id": null,
      "count": 5291
    },
    {
      "_id": "Mac OS X 10.7",
      "count": 16
    },
    {
      "_id": "Belkin Wireless Router",
      "count": 1
    },
    {
      "_id": "Windows",
      "count": 1002
    },
    {
      "_id": "Android",
      "count": 51314
    }
  ]

I'm trying to group all the values where the _id corresponds to the same os and add the count from each element, so I could get something like:

[
   {
    "label": "Windows",
    "value": "9999"
   },
   {
    "label": "Android",
    "value": "8888"
   },
   {
    "label": "iOS",
    "value": "7777"
   },
   {
    "label": "Macos",
    "value": "10000"
   },
   {
    "label": "Other",
    "value": "5000"
   }
]

I'm at a complete lost here, I would really appreciate some help and guidance.

Upvotes: 0

Views: 44

Answers (4)

ajai Jothi
ajai Jothi

Reputation: 2294

Used Array.prototype.reduce and String.prototype.match for your scenario. Hope this helps.

var input = {"devices":[{"_id":"HP Printer","count":1},{"_id":"55UA8990","count":1},{"_id":"Mac OS X 10.5","count":1},{"_id":"Nokia","count":4},{"_id":"Ubuntu Linux","count":3},{"_id":"LG handset","count":1},{"_id":"Samsung Home Audio/Video equipment","count":1},{"_id":"Generic Linux","count":1},{"_id":"Sony handset","count":1},{"_id":"Mac OS X 10.8","count":12},{"_id":"Linux Handheld","count":1},{"_id":"Symbian OS","count":15},{"_id":"RIM BlackBerry","count":28},{"_id":"Apple iPod","count":1},{"_id":"LG BL40","count":1},{"_id":"Slingbox","count":67},{"_id":"Windows XP","count":60},{"_id":"BlackBerry","count":51},{"_id":"Chrome OS","count":7},{"_id":"Eye-Fi Wireless Memory Card","count":6},{"_id":"Mac OS X 10.9","count":62},{"_id":"Mac OS X 10.10","count":215},{"_id":"Windows Vista","count":4},{"_id":"Windows Mobile OS","count":213},{"_id":"Windows 7/Vista","count":394},{"_id":"Mac OS X 10.11","count":303},{"_id":"Samsung TV","count":1},{"_id":"PlayStation Portable","count":1},{"_id":"Mac OS X","count":755},{"_id":"Windows 7","count":612},{"_id":"Apple iPad","count":2597},{"_id":"Ellipsis 8","count":193},{"_id":"Mac OS X 10.12","count":550},{"_id":"Nexus","count":4657},{"_id":"Windows 10","count":772},{"_id":"Windows 8","count":1191},{"_id":"Xbox 360","count":39},{"_id":"Mac OS X 10.6","count":5},{"_id":"Apple iPhone","count":41039},{"_id":"iOS","count":25725},{"_id":"Debian-based Linux","count":9},{"_id":null,"count":5291},{"_id":"Mac OS X 10.7","count":16},{"_id":"Belkin Wireless Router","count":1},{"_id":"Windows","count":1002},{"_id":"Android","count":51314}]};

var output = input.devices.reduce(function(a, b) {
  var match = b._id?b._id.match(/(Mac|Windows|Android|iOS)/):null;
  match = match ? match[0] : 'Others';
  a[match] = (a[match] || 0) + b.count;
  return a;
}, {});

output = Object.keys(output).map(function(k){
  return {
    label: k,
    value: output[k]
  };
});
console.log(output);

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386654

You could use an array with the grouping strings and use a hash table for counting.

var data = { devices: [{ _id: "HP Printer", count: 1 }, { _id: "55UA8990", count: 1 }, { _id: "Mac OS X 10.5", count: 1 }, { _id: "Nokia", count: 4 }, { _id: "Ubuntu Linux", count: 3 }, { _id: "LG handset", count: 1 }, { _id: "Samsung Home Audio/Video equipment", count: 1 }, { _id: "Generic Linux", count: 1 }, { _id: "Sony handset", count: 1 }, { _id: "Mac OS X 10.8", count: 12 }, { _id: "Linux Handheld", count: 1 }, { _id: "Symbian OS", count: 15 }, { _id: "RIM BlackBerry", count: 28 }, { _id: "Apple iPod", count: 1 }, { _id: "LG BL40", count: 1 }, { _id: "Slingbox", count: 67 }, { _id: "Windows XP", count: 60 }, { _id: "BlackBerry", count: 51 }, { _id: "Chrome OS", count: 7 }, { _id: "Eye-Fi Wireless Memory Card", count: 6 }, { _id: "Mac OS X 10.9", count: 62 }, { _id: "Mac OS X 10.10", count: 215 }, { _id: "Windows Vista", count: 4 }, { _id: "Windows Mobile OS", count: 213 }, { _id: "Windows 7/Vista", count: 394 }, { _id: "Mac OS X 10.11", count: 303 }, { _id: "Samsung TV", count: 1 }, { _id: "PlayStation Portable", count: 1 }, { _id: "Mac OS X", count: 755 }, { _id: "Windows 7", count: 612 }, { _id: "Apple iPad", count: 2597 }, { _id: "Ellipsis 8", count: 193 }, { _id: "Mac OS X 10.12", count: 550 }, { _id: "Nexus", count: 4657 }, { _id: "Windows 10", count: 772 }, { _id: "Windows 8", count: 1191 }, { _id: "Xbox 360", count: 39 }, { _id: "Mac OS X 10.6", count: 5 }, { _id: "Apple iPhone", count: 41039 }, { _id: "iOS", count: 25725 }, { _id: "Debian-based Linux", count: 9 }, { _id: null, count: 5291 }, { _id: "Mac OS X 10.7", count: 16 }, { _id: "Belkin Wireless Router", count: 1 }, { _id: "Windows", count: 1002 }, { _id: "Android", count: 51314 }] },
    os = ["Windows", "Android", "iOS", "Mac OS", "Other"],
    result = data.devices.reduce(function (hash) {
        return function (r, a) {
            var key = 'Other';
            os.some(function (o) {
                if (typeof a._id === 'string' && a._id.toLowerCase().indexOf(o.toLowerCase()) !== -1) {
                    key = o;
                    return true;
                }
            });
            if (!hash[key]) {
                hash[key] = { label: key, value: 0 };
                r.push(hash[key]);
            }
            hash[key].value += a.count;
            return r;
        };
    }(Object.create(null)), []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 0

Robert Fines
Robert Fines

Reputation: 720

You could do something like:

var results = [];
devices.forEach(function(d) {
   if(results.length === 0){ //shortcut for the first element
     results.push({label:d._id, value: d.count});
   } else {
       var found = false;
       for(var j =0; j < results.length; j++){
         var i = results[j];
         if(i.label === d._id){
          found = true;
          i.value += d.count;
          results[j] = i;
         }
       });
       if(!found) {
            results.push({label:d._id, value: d.count});
       }
   }
});
return results;

This will iterate over the devices array and find the element in the array that matches and add the count to the value for that item in the array of results. If the item is not found, or it is the first item, a new object is pushed to the results array.

Upvotes: 0

Linek
Linek

Reputation: 1363

  • Create an array of regex values each matching specific OS like .*windows.*.
  • Iterate your data array trying to match each entry's _id with the regex.
  • If it's a match add count value to value in output array. If it's not a match then add to "Other".

How you do it is up to you, it's just a general idea.

Upvotes: 0

Related Questions