Nikhil Menghrajani Nikhil Menghrajani - 5 months ago 8
AngularJS Question

How to save distinct values in an object in javascript?

I have a bunch of log data which is stored in a variable. Each log value contains a camera name and system ip. I want to create an object which has names as all the distinct system ip's and corresponding value as an array which contains all the camera names corresponding to that system ip. Below is my code ---

$http(req).success(function(data){
$scope.logs = data;
$scope.cameras={};
var v =$scope.logs[0].systemIp;
$scope.cameras["v"]=[];
$scope.cameras["v"].push($scope.logs[0].cameraName);
for(i=1;i<$scope.logs.length;i++){
v=$scope.logs[i].systemIp;
var flag=0;
for(j in $scope.cameras){
if(j==="v")
{
flag=1;
break;
}
}
if(flag==0)
{
$scope.cameras["j"]=[];
$scope.cameras["j"].push($scope.logs[i].cameraName);
}
else if(flag==1)
{
$scope.cameras["v"].push($scope.logs[i].cameraName);
}
}});


And this is what my data looks like --

[{
"_id": "57683fd82c77bb5a1a49a2aa",
"cameraIp": "192.16.0.9",
"cameraName": "garage2",
"systemIp": "192.168.0.2"
},
{
"_id": "57683f8e2c77bb5a1a49a2a9",
"cameraIp": "192.16.0.8",
"cameraName": "garage1",
"systemIp": "192.168.0.2"
},
{
"_id": "57683f5e2c77bb5a1a49a2a8",
"cameraIp": "192.16.0.7",
"cameraName": "Back Door",
"systemIp": "192.168.0.4"
}]


When I print $scope.cameras on my console it gives this as the output -

Object { v: Array[3] }


I want by cameras object to look like this --

{ "192.168.0.2" : [ "garage1" , "garage2"] ,
"192.168.0.4" : [ "Back Door"] }


I am new to javascript, any help is appreciated.

Answer

If you are using the Lodash or Underscore library (which I highly recommend), you can just use the _.groupBy() function to do what you are after (along with some other functions to ensure all values are unique).

However, you can also easily implement it yourself:

function groupByDistinct(arr, prop, mapFn) {
    mapFn = mapFn || function (x) { return x; };
    var output = {};
    arr.forEach(function (item) {
        var key = item[prop],
            val = mapFn(item);
        if (!output[key]) {
            output[key] = [val];
            return;
        }
        if (output[key].indexOf(val) < 0) {
            output[key].push(val);
        }
    });
    return output;
}

Use it for your code like so:

$scope.cameras = groupByDistinct(data, 'cameraIp', function (logEntry) { 
    return logEntry.cameraName;
});