Ray
Ray

Reputation: 325

Group or summarize Javascript array

var json =
[
   {
      id: 11,
      name:"app1",
      family:"apps",
      caseID: 123,
      order:1
   },
   {
      id: 12,
      name:"app1",
      family:"apps",
      caseID: 123,
      order:2
   },
   {
      id: 13,
      name:"app1",
      family:"apps",
      caseID: 123,
      order:3
   },
   {
      id: 14,
      name:"app2",
      family:"tools",
      caseID: 129,
      order:1
   },
   {
      id: 15,
      name:"app2",
      family:"tools",
      caseID: 129,
      order:2
   },
   {
      id: 16,
      name:"app3",
      family:"utils",
      caseID: 120,
      order:1
   },
   {
      id: 17,
      name:"app3",
      family:"utils",
      caseID: 120,
      order:2
   },
      id: 18,
      name:"app3",
      family:"utils",
      caseID: 150,
      order:null
   }
  ] 

Hello, I would like to sort the array above by the highest "order" key and return the filtered array below. The common key is the caseID. Also, If the order key is null return it. I've searched and tested some functions and loops but cannot seem to get it rite. Any help will be much appreciated. I'd prefer es2015 if possible. Thank you!

filtered = 
 [

  {
      id: 13,
      name:"app1",
      family:"apps",
      caseID: 123,
      order:3  
   },
   {
      id: 15,
      name:"app2",
      family:"tools",
      caseID: 129,
      order:2
   },
   {
      id: 17,
      name:"app3",
      family:"utils",
      caseID: 120,
      order:2
   },
   {
      id: 18,
      name:"app3",
      family:"utils",
      caseID: 150,
      order:null
   }
  ]

Upvotes: 0

Views: 88

Answers (7)

亚里士朱德
亚里士朱德

Reputation: 517

Sort by order and caseID and then filter by caseID,Here is the code:

var json =
[
   {
      id: 11,
      name:"app1",
      family:"apps",
      caseID: 123,
      order:1
   },
   {
      id: 12,
      name:"app1",
      family:"apps",
      caseID: 123,
      order:2
   },
   {
      id: 13,
      name:"app1",
      family:"apps",
      caseID: 123,
      order:3
   },
   {
      id: 14,
      name:"app2",
      family:"tools",
      caseID: 129,
      order:1
   },
   {
      id: 15,
      name:"app2",
      family:"tools",
      caseID: 129,
      order:2
   },
   {
      id: 16,
      name:"app3",
      family:"utils",
      caseID: 120,
      order:1
   },
   {
      id: 17,
      name:"app3",
      family:"utils",
      caseID: 120,
      order:2
   }, {
      id: 18,
      name:"app3",
      family:"utils",
      caseID: 150,
      order:null
   }
 ]
var obj = {}
var arr = json.sort(function(a, b) {
  return b.order - a.order
}).sort(function(a, b) {
  return a.caseId - b.caseId
}).filter(function(item, index, array){
  return obj.hasOwnProperty(item.caseID) ? false : (obj[item.caseID] = true)
})
console.log(arr)

demo: http://jsbin.com/qabehorike/edit?js,console,output

Upvotes: 0

TechnoCrat
TechnoCrat

Reputation: 708

This should help you filter array of objects.

            var filteredMap = {};
            json.forEach(function (item) {
                filteredMap[item.caseID] = item;
            });
            var filteredArray = [];
            for (var key in filteredMap) {
                filteredArray.push(filteredMap[key]);
            }
            console.log(JSON.stringify(filteredArray));

Upvotes: 0

Jonas Wilms
Jonas Wilms

Reputation: 138427

You could use a caseID hashtable and override results you find later if order is higher:

  const result = [], hash = {};

  for(const el in json) {
   const exists = hash[el.caseId];
   if(exists) {
     if(el.order > exists.order)
       Object.assign(exists, el);
   } else {
       result.push(hash[el.caseId] = {...el});
   }
 }

Upvotes: 2

brk
brk

Reputation: 50326

Use reduce method to create an object where the keys will be the caseID.While creating the object check if the value of the order is more or less that the current order value.If the current value is less the than the new value, replace it with new value.

Then use Object.values(object) to create an array of values from the object

var json = [{
    "id": 11,
    "name": "app1",
    "family": "apps",
    "caseID": 123,
    "order": 1
  },
  {
    "id": 12,
    "name": "app1",
    "family": "apps",
    "caseID": 123,
    "order": 2
  },
  {
    "id": 13,
    "name": "app1",
    "family": "apps",
    "caseID": 123,
    "order": 3
  },
  {
    "id": 14,
    "name": "app2",
    "family": "tools",
    "caseID": 129,
    "order": 1
  },
  {
    "id": 15,
    "name": "app2",
    "family": "tools",
    "caseID": 129,
    "order": 2
  },
  {
    "id": 16,
    "name": "app3",
    "family": "utils",
    "caseID": 120,
    "order": 1
  },
  {
    "id": 17,
    "name": "app3",
    "family": "utils",
    "caseID": 120,
    "order": 2
  }, {
    "id": 18,
    "name": "app3",
    "family": "utils",
    "caseID": 150,
    "order": null
  }
]

var m = json.reduce(function(acc, curr, index) {
  if (acc[curr['caseID']] === undefined) {
    acc[curr['caseID']] = curr;

  } else {
    if (acc[curr['caseID']].order < curr.order) {
      acc[curr['caseID']] = curr;
    }
  }
  return acc;
}, {})
console.log(Object.values(m))

Upvotes: 0

Kirill
Kirill

Reputation: 414

In ES6:

json.sort((a, b) => a.caseID > b.caseID);
let bad_order = json.filter(v => v.order === null);
let good_order = json.filter(v => v.order !== null);

Example

In ES5:

json.sort(function(a, b) { return a.caseID > b.caseID; });

var bad_order = [];
var good_order = [];

for(var i = 0; i < json.length; i++){
  if(json[i].order === null)
    bad_order.push(json[i]);
  else
    good_order.push(json[i]);
}

Example

Upvotes: 0

Mark
Mark

Reputation: 92450

I would start by getting rid of dupes. You can do this with reduce() and assigning to an object keyed to caseID. You can simultaneously avoid any object with a smaller order than one you've already seen. Then you can take the values of that hash which will be the unique objects base on caseID and sort them like you normally would. For example:

var json = [{   "id": 11,   "name":"app1",   "family":"apps",   "caseID": 123,   "order":1},{   "id": 12,   "name":"app1",   "family":"apps",   "caseID": 123,   "order":2},{   "id": 13,   "name":"app1",   "family":"apps",   "caseID": 123,   "order":3},{   "id": 14,   "name":"app2",   "family":"tools",   "caseID": 129,   "order":1},{   "id": 15,   "name":"app2",   "family":"tools",   "caseID": 129,   "order":2},{   "id": 16,   "name":"app3",   "family":"utils",   "caseID": 120,   "order":1},{   "id": 17,   "name":"app3",   "family":"utils",   "caseID": 120,   "order":2},{   "id": 18,   "name":"app3",   "family":"utils",   "caseID": 150,   "order":null},] 

// get just the filtered items based on caseID
// picking out only the largest
let filtered = json.reduce((a,c) => {
      if (!a[c.caseID] || a[c.caseID]['order'] < c.order) a[c.caseID] = c
      return a
  }, {})

// basic sort
let result = Object.values(filtered).sort((a,b) => b.order - a.order)
console.log(result)

Upvotes: 2

Nikhil Aggarwal
Nikhil Aggarwal

Reputation: 28475

You can try following

Method

  1. Create an object with unique case ID as key and value being the item with highest order
  2. Sort based on order

// Code goes here

var json = [{"id":11,"name":"app1","family":"apps","caseID":123,"order":1},{"id":12,"name":"app1","family":"apps","caseID":123,"order":2},{"id":13,"name":"app1","family":"apps","caseID":123,"order":3},{"id":14,"name":"app2","family":"tools","caseID":129,"order":1},{"id":15,"name":"app2","family":"tools","caseID":129,"order":2},{"id":16,"name":"app3","family":"utils","caseID":120,"order":1},{"id":17,"name":"app3","family":"utils","caseID":120,"order":2},{"id":18,"name":"app3","family":"utils","caseID":150,"order":null}];
  
  
  var map = {};

  // Create a map of unique case ID's with highest order
  json.forEach((item) => {
    if(map[item.caseID]) {
        if(map[item.caseID].order < item.order) {
          map[item.caseID] = item;
        }
    } else {
      map[item.caseID] = item;
    }
  });
  
  // Sorting the array based on order
  var result = Object.values(map).sort((a,b) => b.order-a.order);
  console.log(result);
  

Upvotes: 0

Related Questions