1

I have an app which gets data from the database (MongoDB) in JSON format. The returned data contains nested arrays and I want to access the values in the nested arrays. The returned JSON format looks like this:

[
 {"_id": "81724587125","name": "Object 1", "arrayOne":["1","2","3"]},
 {"_id": "87687687687","name": "Object 2", "arrayOne":["4","5","6"]}
]

Now what I want is to retrieve the values from arrayOne from all objects and push them into a single array like so:

combinedValues:["1","2","3","4","5","6"]

To achieve this I have used Nested For Loops below is my actual code:

 function myFunc(result){

    $scope.clients = [];

    for(var i = 0; i < result.length; i++){
      for(var x = 0; x < result[i].sectorClients.length; x++){
        $scope.clients.push(result[i].sectorClients[x]);
      }
    }       
};

The above code works fine and does what I want it to do.

My Question:

Is using nested for loops for this particular situation a good programming practice? Is there a better way of achieving the same functionality? Ive heard people say that nested for loops can be "expensive" processing wise.

4
  • You can write MapReduce query to get the same result directly from Mongo.
    – Mahdi
    Commented Mar 14, 2016 at 10:03
  • @Mahdi Thank you for the comment. Thats good advice I'll have look into that now. Do you have an example links that might be helpful? Commented Mar 14, 2016 at 10:06
  • 1
    Any MapReduce tutorial on Mongo should get you started.
    – Mahdi
    Commented Mar 14, 2016 at 10:22
  • Nested for loops typically aren't expensive. But, of course, saying they're 'not expensive' is as subjective as saying they are. Depends what you're doing inside the loop, or what you're iterating over. In your case, it's fine. Commented Mar 14, 2016 at 11:46

4 Answers 4

1

As I mentioned in the comments you can get the same result directly from MongoDB using a MapReduce query; However a cleaner JavaScript equivalent for your nested loops can be something like this:

var data = [
 {"_id": "81724587125","name": "Object 1", "arrayOne":["1","2","3"]},
 {"_id": "87687687687","name": "Object 2", "arrayOne":["4","5","6"]}
];

var result = data.reduce(function (previousValue, currentValue, currentIndex, array) {
    return previousValue.arrayOne.concat( currentValue.arrayOne );
});
0
2

Nested loops are expensive when they both iterate over independent data in a "criss-cross" fashion, because they may represent a O(n^2) algorithm that can be made more efficient. You may think of such loops as describing the program "for every element in X, loop over every element in Y again".

This is not one of those cases. Your data are an array of objects, each containing further arrays of objects. A nested loop here is not only fine: it's completely expressive and appropriate.

0
-1

in the case, you needn't use "puth" function, push every tiny element into the array;because you can operate the whole array eg: [1,2,3].concat([4,5,6]) => [1, 2, 3, 4, 5, 6]

then you can improve your code by reducing the loop

-1

You can use map function of array to get the properties (arrayOne) you want, and create a flattened array from array of arrays (array of arrayOnes) using reduce.

var clients = results
  .map(function(r){ return r.arrayOne; })
  .reduce(function(prev, curr) { return prev.concat(curr); }, []);
// ["1", "2", "3", "4", "5", "6"]

Resources:

1
  • 1
    This seems like only a slight variation on the solution already provided in the accepted answer, but without addressing the conceptual question the OP asked. Keep in mind that unlike StackOverflow, questions here on on Programmers.SE are rarely looking for a specific piece of code.
    – Ixrec
    Commented Mar 18, 2016 at 14:42

Not the answer you're looking for? Browse other questions tagged or ask your own question.