Firstly, the Math function could be done within the if() test loop as that would ignore p == q items.
However, for situations such as this, I would suggest that it is more typical to have two loops - the outer loop going from 0 to the penultimate item and the inner loop going from the outer loop's counter+1 to the last item:
for (let i = 0; i < items.length - 1; i++) {
for (let j = i + 1; j < items.length; j++) {
// check values at i and j
)
}
This way, i and j will never be the same and you never need to iterate over the entire array for every instance of i.
Answer from ATD on Stack OverflowAre nested for loops (in general - for loops) expensive in JavaScript? AFAIK prototype.map() is an alternative to for loop when it comes to code organisation but doesn't do well when memory, speed is taken into account. If for loops are expensive, what could be a performant alternative to nested for loop?
javascript - What is the best alternative to nested for loops? - Stack Overflow
performance - Nested For Loops JavaScript - Software Engineering Stack Exchange
Nested for loops vs forEach and nested filter forEach
javascript - Optimizing a nested for loop over JS array of objects - Code Review Stack Exchange
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 );
});
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.
Personally I find functional programming reads easier than nested for loops and has less room for error during setup:
arr.forEach((value1, indexL1) => {
const remainingNums = arr.filter((null, i) => indexL1 < i);
remainingNums.forEach(...)
});I think this approach is slower though. Is it a lot slower to the point it would be looked down on during an algorithm test? I think no matter what you're dealing with O(n^2) since there is still a nested loop.
As others have already mentioned, Array.prototype.filter() might be the simplest approach (or Array.prototype.reduce() could also be used but would require more conditional logic). It would typically be slower than the nested for loops because it would be adding additional function calls, but for small data sets it typically wouldn't be noticeable. For example, I did a search on Google for "jsperf filter nested loop" and found this jsPerf test.
Using Array.prototype.filter() on A2, pass a callback function that returns true when the value at property value is included in A1 by checking A1.indexOf() for a value greater than -1.
const result = A2.filter(function(o) {
return A1.indexOf(o.value) > -1;
});
This can be simplified to a single line using an ES-6 arrow function and Array.prototype.includes() (Not supported by IE):
const result = A2.filter(o => A1.includes(o.value));
Try it in this snippet:
var A1 = ["1","2","3","4"];
var A2 = [
{label:"one", value:"1"},
{label:"two", value:"2"},
{label:"three", value:"3"},
{label:"four", value:"4"},
{label:"five", value:"5"},
{label:"six", value:"6"},
];
const result = A2.filter(o => A1.includes(o.value));
console.log('result', result);
If you wanted to use Underscore.js, _.filter() and _.includes() could be used to filter out any object in A2 without a value for the value property contained in A1. Expand the snippet below for a demonstration.
var A1 = ["1","2","3","4"];
var A2 = [
{label:"one", value:"1"},
{label:"two", value:"2"},
{label:"three", value:"3"},
{label:"four", value:"4"},
{label:"five", value:"5"},
{label:"six", value:"6"},
];
const result = _.filter(A2, function(o) { return _.includes(A1, o.value);});
console.log('result', result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
There is an Underscore helper _.pluck() but that is used to collect a value from each item in a collection at a given property (similar to Array.prototype.map().
Lodash also has the same helpers: _.filter() and _.includes().
var A1 = ["1","2","3","4"];
var A2 = [
{label:"one", value:"1"},
{label:"two", value:"2"},
{label:"three", value:"3"},
{label:"four", value:"4"},
{label:"five", value:"5"},
{label:"six", value:"6"},
];
const result = _.filter(A2, function(o) { return _.includes(A1, o.value);});
console.log('result', result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
Though some question whether libraries like lodash and underscore are really needed anymore. For a discussion on that, check out this article.
You can use some built in functions instead of the for loops.
var result = A2.filter(e => A1.includes(e.value));
I can't say if this is much faster, since those functions still loop through the arrays. You'll have to time this with some large input to test.
Be aware that Internet Explorer doesn't support .includes or arrow functions. IE friendly version:
var result = A2.filter(function(e) {return A1.indexOf(e.value) !== -1});
My mind blanks as how replace nested loops with a faster and perhaps a less wasteful way? I know they can’t always be replaced but when is a good time to replace them.
I figure this will come with time but does anyone have any general or specific tips, use cases or examples of how to replace loops or improve on this. I feel like this what’s turning good ideas into lame or unimpressive by speed issues.
Been practicing algorithms in c, JavaScript and python for about a year and I seem to constantly get slower solutions when doing leetcode for example. Self taught udemy, books and cs50x.
Ideally I like to refactor and improve a python script I created with interns and others that read 100,000 reviews and creates moods similarity recommendation engine that indexed and sorts by mood but it take 7-8 days to update it. But then I upload csv to database and works in fast. But had times where something went wrong and took 21 days to get a file. But before doing that I like to learn in general so I can make better decisions coding.
Just like Perl,
loop1:
for (var i in set1) {
loop2:
for (var j in set2) {
loop3:
for (var k in set3) {
break loop2; // breaks out of loop3 and loop2
}
}
}
as defined in EMCA-262 section 12.12. [MDN Docs]
Unlike C, these labels can only be used for continue and break, as Javascript does not have goto.
Wrap that up in a function and then just return.