I will start with a small description of the result I want to get:
Let's imagine we have a collection called " Elements " which contains the 4 documents: 'a','b','c' and 'd'. I want to iterate over " Elements " and insert in a new collection called " Queries " the pairs :
(a,b);(a,c);(a,d);(b,a);(b,c)...(d,a);(d,b);(d,c). => which means " Queries " will contain (in this example) 4*3 = 12 pairs of elements (documents) at the end.
Here is the code I'm using (it's a method in meteor server triggered by a click on a button):
'Queries': function() {
var allElements = Elements.find();
allElements.forEach(function(myLeftElement){ //First forEach
allElements.forEach(function(myRightElement){// Nested forEach
if(myLeftElement._id !== myRightElement._id){
Queries.insert( {myLeftElement : myLeftElement._id, myRightElement : myRightElement._id} );
}
}); //End Of nested forEach
}); //End Of First forEach
}
In fact it works only for the first "myLeftElement" with all other elements "myRightElement" but stops there: it inserts, into "Queries" collection, the pairs: [(a,b);(a,c) and (a,d)] and then stops.
Since I am a beginner in web developement in general and in using Meteor in particular, I am seeking for your help.
1) I need to understand why once the nested cursor method "forEach" stops, the whole function stops.
2) How can I improve the code to get the result I really want: to every element of my collection "myLeftElement" there is a forEach method that creates pairs with all other elements "myRightElement". And then moves to the next "myLeftElement" and do the same till the end.
Thanks,
Here is a working example of iterating over an Array with vanilla JavaScript that gets the expected result:
var elements = ['a', 'b', 'c', 'd']; var result = []; elements.forEach(function(item) { // Create a copy of the current array to work with var elements_copy = elements.slice(0); var temp_array = []; /* Delete the current `item` from the array since we don't want duplicate 'a:a' items in the array. IMPORTANT: There are better ways of doing this, see: http://stackoverflow.com/questions/3954438/remove-item-from-array-by-value */ elements_copy.splice(elements_copy.indexOf(item), 1); elements_copy.forEach(function(child_item) { temp_array.push(item + "," + child_item); }); result.push(temp_array); }); console.log(result);
You'll need to make sure you open the Console in the Developer Tools to see the result.
When you're starting out I recommend getting working scenarios with the least complexity -- like here where I removed Meteor and Mongo out of the picture -- to ensure that your logic is sound then working in the rest from there.
So, to answer your questions directly:
Hope that helps!
The @cynicaljoy's answer inspired me in two ways:
So thanks a lot.
Now after taking the necessary modifications, here is one solution that actually works fine using Meteor and Mongodb codes:
'Queries' : function() {
var allElements = Elements.find().map(function(item){return item._id} ); /* this returns an array of item._id of all elements*/
var totalItems = allElements.length;
var itemsCounter = 0;
var withoutLeftItem;
while(itemsCounter < totalItems){
withoutLeftItem=_.without(allElements,allElements[itemsCounter] ); /*The function _.without(array, *items) used in underscore.js returns array with specified items removed */
withoutLeftItem.forEach(function(myRightElement){
Queries.insert( {myLeftElement : allElements[itemsCounter], myRightElement : myRightElement} );
});
itemsCounter++;
}
}
I am still curious to understand why the solution presented in the question was not working as it was supposed and also to see an optimized code in terms of memory usage.
Hope this helps other people. Thanks all
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.