I've decided to share my two pence on the matter. It's quite a process but let's see what comes of it:
Testing Environment
First, let me show you how I tested this. I tested with the following code:
function logTime(fn, msg){
var t = Date.now();
for(var i = 0; i < 1000; i++){
fn();
}
document.body.innerHTML += msg
document.body.innerHTML += Date.now() - t;
document.body.innerHTML += 'ms<br />';
}
Now I know this isn't the most accurate, but I believe both functions have the same disadvantages here, so executing it 1000 times in a row will show the better one.
Larger Sample Creation
Now, I also built a function to give it a bit of a bigger sample input. The small differences are hard to notice any differences with, but my solution is significantly faster when it comes to larger arrays. Heres the function I used to randomly generate a large arrays of arrays:
function compriseArrays(){
var randAmount = Math.round(Math.random() * 10);
var result = new Array();
for(var i = 0; i < randAmount; i++){
result[i] = new Array();
var count = 0;
var randSize = Math.round(Math.random() * 500);
for(var r = 0; r < randSize; r++){
var plus = Math.round(Math.random() * 5);
count += plus;
result[i][r] = count;
}
}
return result;
}
This only gets ran once, and sometimes creates larger and sometimes smaller arrays, but usually big enough to allow this test to make results obvious.
The Solution
Now my solution is to do a quick loop through the arrays to find the shortest one, significantly cutting down on the potential time we spend analysing every array:
function findCommon(arrays){
var result = [];
// First, find the shortest array of them all
var array = arrays.length-1;
for(var i = arrays.length-1; i >= 0; i--){
if(arrays[i].length < arrays[array].length) array = i;
}
// Then execute the already existing function
for(var i = arrays[array].length-1; i >= 0; i--){
var j = arrays.length-1;
for(; j > 0; j--){
if(arrays[j].indexOf(arrays[array][i]) < 0) break;
}
if(j == 0) result.push(arrays[array][i]);
}
return result;
}
For all intents and purposes, the function is the same as yours, apart from the i >= 0
, which made your function ignore the first item in every array, even though it could be a match. Now lets put this to the test:
The Results
function compriseArrays(){
var randAmount = Math.ceil(Math.random() * 10);
var result = new Array();
for(var i = 0; i < randAmount; i++){
result[i] = new Array();
var count = 0;
var randSize = Math.ceil(Math.random() * 500);
for(var r = 0; r < randSize; r++){
var plus = Math.ceil(Math.random() * 5);
count += plus;
result[i][r] = count;
}
}
return result;
}
// My Function
function findCommon(arrays){
var result = [];
var array = arrays.length-1;
for(var i = array; i > 0; i--){
if(arrays[i].length < arrays[array].length) array = i;
}
for(var i = arrays[array].length-1; i >= 0; i--){
var j = arrays.length-1;
for(; j > 0; j--){
if(arrays[j].indexOf(arrays[array][i]) < 0) break;
}
if(j == 0) result.push(arrays[array][i]);
}
return result;
}
// OP's Functions
var findCommonElements = function(arrs) {
var resArr = [];
for (var i = arrs[0].length - 1; i >= 0; i--) {
for (var j = arrs.length - 1; j > 0; j--) {
if (arrs[j].indexOf(arrs[0][i]) == -1) {
break;
}
}
if (j === 0) {
resArr.push(arrs[0][i]);
}
}
return resArr;
}
function logTime(fn, msg){
var t = Date.now();
for(var i = 0; i < 1000; i++){
fn();
}
document.body.innerHTML += msg
document.body.innerHTML += Date.now() - t;
document.body.innerHTML += 'ms<br />';
}
var largeArray = compriseArrays();
var allitems = 0;
for(var i = 0; i < largeArray.length; i++){
for(var j = 0; j < largeArray[i].length; j++){
allitems++;
}
}
var findCommonResult = findCommon(largeArray).join(', ');
var findCommonElementsResult = findCommon(largeArray).join(', ');
logTime(function(){
findCommon(largeArray);
}, 'findCommon() in Array(length: ' + allitems + ') -> [' + findCommonResult + '] : ');
logTime(function(){
findCommonElements(largeArray);
}, 'findCommonElements() in Array(length: ' + allitems + ') -> [' + findCommonElementsResult + '] : ');
Note: If the above snippet shows the same amount of time consumed, please run it again, as there is a slight chance that the first array is the shortest array, and therefor both functions would take the same amount of time. If my function is slower, try again as you might have gotten a significantly small random set of arrays back, and I explain below why this could be slower.
Now, this function will usually do better than yours as I am using already defined variables to find the shortest route through this. Only when the arrays you are scanning are really small, or one of the earliest arrays is the shortest, or the amount of arrays is higher than the amount of entries in the first one, does the advantage dissappear, as the loop through the array length may extend the time it takes to execute the function.