0

My array Looks like this

var List = [
   {qid: 1, ID: 1, text: "XXX",...},
   {qid: 1, ID: 2, text: "XXX",...},
   {qid: 1, ID: 3, text: "XXX",...},
   {qid: 2, ID: 4, text: "XXX",...},
   {qid: 2, ID: 5, text: "XXX",...},
   {qid: 3, ID: 6, text: "XXX",...}, 
   {qid: 3, ID: 7, text: "XXX",...}, 
   {qid: 3, ID: 8, text: "XXX",...}, 
];

I want to query the array so that the final list looks like this

var FinalList = [
   {qid: 1, ID: 3, text: "XXX",...},
   {qid: 2, ID: 5, text: "XXX",...},
   {qid: 3, ID: 8, text: "XXX",...}, 
];

qid can have multiple ID but the last entry will be the one selected for the FinalList[] array

I want to use something like group by on qid and get last row entered based on qid in angularcontroller.js.

I tried using the reduce function but it does not give me exactly what i want

its been just a month since I have started using angularjs any help will be greatly appreciated

Addition:

I tried doing this

angular.forEach($scope.selectedList, function (item) {                

    var found = $filter('filter')($scope.selectedList, { QuesID: item.qid});
    $scope.FinalList .push(found[found.length - 1]);

    $scope.List = $scope.List .filter(function (o1) {
        return !$scope.List.some(function (o2) {
            return o1.qid=== o2.qid;
        });
    });
});

I get the first item not the subsequent

DotNetBeginner
  • 412
  • 2
  • 15
  • 34

2 Answers2

1

Its a Javascript question more than an angularJS one. Ok, here goes:

Sort the array first: (Credits : https://stackoverflow.com/a/8837511/6347317)

var sortedList = List.sort(function(a, b){
    var keyA = a.qid;      
    keyB = b.qid;        
if(keyA < keyB) return -1;  
if(keyA > keyB) return 1;   
return 0;
});

Assign the required variables:

var firstqid=sortedList[0].qid; //first object
var finObjArr = [];  //final array
var finObj={};  //empty object to keep track of the object to be inserted in final array
var lastObj = sortedList.slice(-1)[0]; //last object of sorted array
var flag = 0;  //flag to not insert any more object to final result if the last unique qid is reached

Loop through array and get the result: (finObjArr will have the desired output)

    sortedList.forEach(function(obj) { 
       var qidkey = obj.qid;
   //we are checking if current qid is same as the last one. this is to determine the last object with a qid key and then pushing the previous object (held in finObj) to the final array
        if (qidkey != firstqid)
     { 
           firstqid=qidkey;
          finObjArr.push(finObj);
    }
//If the qid is same as earlier one, then make the current object as finObj and if its the last unique qid, inset the last object in the array in final array and set the flag so that no more inserts happen into final array
    if (qidkey == firstqid)
     {       
        finObj = obj;
         if (qidkey == lastObj.qid && flag == 0) {
           finObjArr.push(lastObj);
             flag=1;
           }
    }
    })

Please check if this works.

Note: I was not sure if you need the sort on the array. If it already comes in the required order, no need to sort and you can directly run the forEach. Else you will have to write a sort function to have the array in the required order for forEach

Vijay Venugopal Menon
  • 1,510
  • 1
  • 14
  • 20
1

You can use a combination of reduce and map to solve this.

First use reduce to group your array by qid:

var grouped = List.reduce(function(agg, x){
    (agg[x['qid']] = agg[x['qid']] || []).push(x);
    return agg;
}, {});

then map the values of this group, with the element with the highest ID. You can find the element with the highest ID using another reduce within this map:

var result = Object.values(grouped).map(function(grp){
   return grp.reduce(function(a, b){
       return a['ID'] > b['ID'] ? a : b;
   });
});

This is in my opinion the most clean solution.

Here is a Plunker showing it in action

Nikolaj Dam Larsen
  • 5,455
  • 4
  • 32
  • 45