0

In my Angularjs application, I have the following json :

$scope.listA =

[
  {
    "bId":777,
    "cId":4,
    "ctNm":"Software"
  },
  {
    "bId":777,
    "cId":2,
    "ctNm":"Hardware"
  },
  {
    "bId":777,
    "cId":1,
    "ctNm":"Malware"
  }
] 

And I need to convert this array in such a way that each json object of the array should contain items array of objects.

The logic to populate this items array of objects for each of this $scope.listA json object is to go and check in $scope.listB array of json objects, if that particular cId exist. If yes, keep all those json objects of $scope.listB under items array of each object in $scope.listA.

$scope.listB =

 [
  {
    "bId":0,
    "cId":2,
    "clsxId":24,
    "ctNm":"Hardware",
    "clNm":"Out 1"
  },
  {
    "bId":0,
    "cId":1,
    "clsxId":99,
    "ctNm":"Malware",
    "clNm":"Srv"
  },
  {
    "bId":0,
    "cId":2,
    "clsxId":26,
    "ctNm":"Hardware",
    "clNm":"Buss"
  },
  {
    "bId":0,
    "cId":2,
    "clsxId":67,
    "ctNm":"Hardware",
    "clNm":"Pait"
  }
]

So the finally modified $scope.listA, should be as shown below :

[
  {
    "bId":777,
    "cId":4,
    "ctNm":"Software",
    "items":[

    ]
  },
  {
    "bId":777,
    "cId":2,
    "ctNm":"Hardware",
    "items":[
      {
        "bId":0,
        "cId":2,
        "clsxId":24,
        "ctNm":"Hardware",
        "clNm":"Out 1"
      },
      {
        "bId":0,
        "cId":2,
        "clsxId":26,
        "ctNm":"Hardware",
        "clNm":"Buss"
      },
      {
        "bId":0,
        "cId":2,
        "clsxId":67,
        "ctNm":"Hardware",
        "clNm":"Pait"
      }
    ]
  },
  {
    "bId":777,
    "cId":1,
    "ctNm":"Malware",
    "items":[
      {
        "bId":0,
        "cId":1,
        "clsxId":99,
        "ctNm":"Malware",
        "clNm":"Srv"
      }
    ]
  }
]

The solution in either under score or in angular js util functions, both are fine for me. I prefer not to use for loop any other way is fine, foreach, map, etc

2
  • 1
    please post some of your effort . Commented Nov 4, 2015 at 14:16
  • I tried with angular. forEach, inside that I am using listB.map, to get all the matching cIds and pushing all these matching indexes into an array and then iterating lstA, inside again I have foreach of lisB to push all the matching indexes, here for index I am using count variable to increment. But I felt there must some smart and simple way to do it. Commented Nov 4, 2015 at 14:22

2 Answers 2

2

Try something like this:

for (var a = 0; a < $scope.listA.length; a++) {
    var itemInA = $scope.listA[a];
    itemInA.items = [];
    for (var b = 0; b < $scope.listB.length; b++) {
        var itemInB = $scope.listB[b];
        if (itemInA.cId === itemInB.cId) {
            itemInA.items.push(itemInB);
        }
    }
}

This will loop through each of the items in your $scope.listA and add a items array to it. Then it will loop through each item in $scope.listB and if the item from $scope.listB has the same cId as the current item in $scope.listA, then it will push it onto the items array of the current item in $scope.listA.

See this working example, which will print the resulting listA out to the console log.

var listA = [{
  "bId": 777,
  "cId": 4,
  "ctNm": "Software"
}, {
  "bId": 777,
  "cId": 2,
  "ctNm": "Hardware"
}, {
  "bId": 777,
  "cId": 1,
  "ctNm": "Malware"
}];

var listB = [{
  "bId": 0,
  "cId": 2,
  "clsxId": 24,
  "ctNm": "Hardware",
  "clNm": "Out 1"
}, {
  "bId": 0,
  "cId": 1,
  "clsxId": 99,
  "ctNm": "Malware",
  "clNm": "Srv"
}, {
  "bId": 0,
  "cId": 2,
  "clsxId": 26,
  "ctNm": "Hardware",
  "clNm": "Buss"
}, {
  "bId": 0,
  "cId": 2,
  "clsxId": 67,
  "ctNm": "Hardware",
  "clNm": "Pait"
}];


for (var a = 0; a < listA.length; a++) {
    var itemInA = listA[a];
    itemInA.items = [];
    for (var b = 0; b < listB.length; b++) {
        var itemInB = listB[b];
        if (itemInA.cId === itemInB.cId) {
            itemInA.items.push(itemInB);
        }
    }
}

console.log(JSON.stringify(listA, null, 2));

Output:

[
  {
    "bId": 777,
    "cId": 4,
    "ctNm": "Software",
    "items": []
  },
  {
    "bId": 777,
    "cId": 2,
    "ctNm": "Hardware",
    "items": [
      {
        "bId": 0,
        "cId": 2,
        "clsxId": 24,
        "ctNm": "Hardware",
        "clNm": "Out 1"
      },
      {
        "bId": 0,
        "cId": 2,
        "clsxId": 26,
        "ctNm": "Hardware",
        "clNm": "Buss"
      },
      {
        "bId": 0,
        "cId": 2,
        "clsxId": 67,
        "ctNm": "Hardware",
        "clNm": "Pait"
      }
    ]
  },
  {
    "bId": 777,
    "cId": 1,
    "ctNm": "Malware",
    "items": [
      {
        "bId": 0,
        "cId": 1,
        "clsxId": 99,
        "ctNm": "Malware",
        "clNm": "Srv"
      }
    ]
  }
]
Sign up to request clarification or add additional context in comments.

4 Comments

In some post I read, using for loop in angularjs is not recommended. Could you please do the same with angular.foreach, because if you use angular for each then we need to manually compute index for each iteration, if I go with your solution and I am little concern with that.
Check out this link. Depending on the actual content of the loop, angular's foreach is actually around 84% slower than just using a native for loop. There's no need to add overhead of a library method when you can do it just as easily with native code.
Or here is another more recent comparison, showing that angular's forEach is actually the slowest of 9 different methods of for looping.
yes, I could able to recollect that suggestion not use for loop is in handling promises when we need to make multiple http requests at a time, etc. But here as there are no promises, http requests, ect I feel your solution is the best and also as per the references that you have provided. So I am accepting the answer.
1

You can try this,

$scope.listA.forEach(function(aItem){
 aItem.Items =[];
 aItem.Items.addRange($scope.listB.where(function(bItem){return aItem.cId == bItem.cId;}));
});

here, I have used some extensions, I created for javascript array

Object.defineProperty(Array.prototype, "addRange", {
 value: function (values) {
    for (var i = 0; i < values.length; i++) {
        this.push(values[i]);
    }
    return this;
  }, enumerable: false
});

Object.defineProperty(Array.prototype, "where", {
 value: function (Predicate) {
    var arr = [];
    for (var i = 0; i < this.length; i++) {
        if (Predicate(this[i])) arr.push(this[i]);
    }
    return arr;
  }, enumerable: false
});

it is bit friendly for c# developer to use it like lambda expression

1 Comment

u can use native for loop in apposed to forEach as suggested by @Madasu K

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.