3

If I have two arrays as parameters how can I find the starting index where the second parameter occurs as a sub-array in the array given as the first parameter.

E.g.: [5,9,3,6,8], [3,6] should return 2.

Is there a function in JavaScript for this, or does it just loop through both of them and compare?

1
  • There is no function for that, you would have to iterate and compare yourself. Commented Mar 6, 2014 at 0:17

7 Answers 7

4
findArrayInArray = function(a, b) {
    var ai = a.length
    ,   bi = b.length;
    for(var i=0; i<ai; i++) {
        if (a[i] === b[0]) {
            if(bi === 1) return i;
            for(var x=1; x<bi; x++) {
                if(a[i+x] === b[x]) {
                    if(x === bi-1) return i;
                } else {
                    break;
                }
            }
        }
    }
}

var arr1 = [5,9,3,6,8];
var arr2 = [3,6];

console.log(findArrayInArray(arr1,arr2)); // 2

http://jsfiddle.net/ymC8y/3/

Sign up to request clarification or add additional context in comments.

2 Comments

Seems to fail a couple of the test cases here: jsfiddle.net/jfriend00/uPwFU. In particular, it seems to not handle the case where arr2.length == 1,
@jfriend00 thanks, fixed it and also did some performance tweaks: jsperf.com/findsubarrayindex
1

In direct answer to your question, there is no built in function in JS to look in an array for a sub-array.

You will have to do some sort of brute force looping search like this or use some external library function that already has array comparison logic. Here's what a brute force solution in plain JS looks like:

function findSubArrayIndex(master, sub) {
    for (var m = 0; m < master.length - sub.length + 1; m++) {
        for (var s = 0; s < sub.length; s++) {
            if (master[m + s] !== sub[s]) {
                break;
            } else if (s === sub.length - 1) {
                return m;
            }
        }
    }
    return -1;
}

Working demo: http://jsfiddle.net/jfriend00/mt8WG/


FYI, here's a somewhat performance optimized version of this function:

function findSubArrayIndex(master, sub) {
    var subLen = sub.length, subFirst, m, mlen;

    if (subLen > 1) {
        subFirst = sub[0];
        for (m = 0, mlen = master.length - subLen + 1; m < mlen; m++) {
            if (master[m] === subFirst) {
                for (var s = 1; s < subLen; s++) {
                    if (master[m + s] !== sub[s]) {
                        break;
                    } else if (s === subLen - 1) {
                        return m;
                    }
                }
            }
        }
    } else if (subLen === 1) {
        subFirst = sub[0];
        for (m = 0, mlen = master.length; m < mlen; m++) {
            if (master[m] === subFirst) {
                return m;
            }
        }
    }
    return -1;
}

Working demo: http://jsfiddle.net/jfriend00/CGPtX/

10 Comments

He didn't actually want a for loop in the question!! he said is there a function in JS or just loop!
@user2517028 - I edited the wording in my answer to explain that there is no built in JS solution without looping. Do I really deserve a downvote for offering a solution? Also, your jQuery answer is also just doing looping too (it's just inside the jQuery function).
he said looping in both of them! so this is looping on one of them only, although the performance is worse I suppose, which I said in the answer
@user2517028 - in plain JS, there are no array sequence comparison functions so you have to loop through both arrays unless you are going to use some library function that does the looping for you. I've answered the OP's question AND given them a working solution with a working jsFiddle demo.
@user2517028, I agree this definitely did not deserve a downvote. +1 from me.
|
1
function index (a, b) {
    var as = new String(a),
        bs = new String(b),
        matchIndex = as.indexOf(bs);

    if (matchIndex === -1) {
        return -1;
    } else if (matchIndex === 0) {
        return 0;
    }
    return as.substring(0, matchIndex + 1).match(/,/g).length;
}

console.log(index([5,9,3,6,8], [3, 6]));

4 Comments

I initially thought about casting to a string and using regex, but although it works it's painfully slow doing it this way: jsperf.com/findarrayinarray
Good point. If performance is an issue, then instead of regex, one can use ".split(',')", which should not be that slow.
This seems to pass the test cases here: jsfiddle.net/jfriend00/CJ77u. It returns 0 if the second arg is an empty array - not sure what the function should return for that case. My answer chose to return -1 if the second arg is a zero, but I guess it isn't really specified how that should be handled.
@jfriend00, you're right, it probably should return -1.
1

you could try this

function compareArray(arr1, arr2){
  return arr1.join("") == arr2.join("");
}

this code returns true if the array and its contents are the same and false if the arrays and its contents are not the same

1 Comment

This does not answer question.
0

You can use the javascript built-in String.indexOf method by converting this array to a string.

function subArrIndex(arr, subArr) {
  let a1 = arr.join(" ");
  let a2 = subArr.join(" ")

  let index = a1.indexOf(a2);

  let subStringEarlier = a1.substr(0, index);

  // count number of spaces ' '
  return subStringEarlier.split(' ').length - 1;
}

let arr = [5,9,3,6,8]
let subArr= [3,6]

console.log(subArrIndex(arr, subArr));

P.S

It will not work if the array contains space ' '. You can then use some other delimiter like , or \n.

Comments

0
let array1 = [11, 22, 33];
let array2 = [21, 22, 23];
let array3 = [11, 22, 33];

const compareArray = (a, b) => {
  return JSON.stringify(a) === JSON.stringify(b);
};

console.log(compareArrays(array1, array2));
console.log(compareArrays(array1, array3));

1 Comment

You should add explanation.
-3

Try this - You loop through both arrays and compare each element:

var arr1 = [5,9,3,6,8];
var arr2 = [3,6];

findArrayInArray = function(arr1, arr2) {
  for(var i=0; i<arr1.length; i++) {
    for(var j=0; j<arr2.length; j++){
      if(arr1[i] === arr2[j]){
        return i;
      }
    }
  }
  return false;
}

findArrayInArray(arr1, arr2);

5 Comments

This would only work if arr2.length == 1 because it never compares beyond the first item in arr2.
@jfriend00 I believe it would iterate through each item in arr2 unless there's a match to arr1[i]
When you find the first matching item in this line if(arr1[i] === arr2[j]){, your function returns. It never compares the rest of arr2.
@jfriend00 that's because he wants the index of the first match. we don't care to iterate through the rest of the function if we already have a match - at least that's from my understanding of his question
But, it has to match all the items of arr2, not just the first item in arr2. Look at what it returns here: jsfiddle.net/jfriend00/kLLrd

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.