1

I have an array, arr = [0, 0, 0, 0, 1, 1]. The argument being passed into a function contains this array and also a numeric value which happens to be 1 in this example. My function is called pairwise and looks like this:

function pairwise(arr, arg) {
  ...some code ...
}
pairwise([0, 0, 0, 0, 1, 1], 1);

If an element pair in the array adds up to the second argument passed to the function then I need to add the indices of each unique pair and return the sum of the indices. For this example, the sum would be 10 because index 0 and 4 adds to 1 and also index 1 and 5 add to one, so the sum of indices 0 + 4 + 1 + 5 = 10. I cannot count the same index twice.

Inside my function, I subtract arg from arr[i] inside a for loop that loops over the length of the array. Then I take the result from that subtraction and use arr.indexOf(result) to find the index pair, if it exists. Everything is working fine until I encounter this problem. indexOf only looks for the first occurrence and when I run my code it doesn't count the second 1 in arr so I am unable to get the second pair. My sum is 4 when it should be 10. Here is the rest of my code:

function pairwise(arr, arg) {
  var array = [];
  if (arr.length != 0) {
    for (var i=0; i<arr.length; i++) {
      if (arr.indexOf(arg - arr[i]) != -1) {
        if (array.indexOf(i) === -1 && array.indexOf(arr.indexOf(arg-arr[i])) === -1) {
          if (i !== arr.indexOf(arg - arr[i])) {
            array.push(i,arr.indexOf(arg - arr[i]));
          }
        }  
      }
    }
  } else {
    return 0;
  }
  console.log (array);
  return array.reduce(function(a,b) {return a+b;});
}

pairwise([0, 0, 0, 0, 1, 1], 1); 

I also push the result into an array so I am limited to Array.prototype methods. I tried looking for other methods to use but I can't find any that I can implement with what I am doing. Maybe you know of one easier way to do this? My question is, is there a way to look past the first index match of indexOf. Should I use another method to approach my solution?

Darrell
  • 25
  • 5

2 Answers2

2

My question is, is there a way to look past the first index match of indexOf.

You can use the second parameter fromIndex of indexOf

The indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present.

fromIndex:

The index to start the search at. If the index is greater than or equal to the array's length, -1 is returned, which means the array will not be searched. If the provided index value is a negative number, it is taken as the offset from the end of the array. Note: if the provided index is negative, the array is still searched from front to back. If the calculated index is less than 0, then the whole array will be searched. Default: 0 (entire array is searched).

Example:

var arr = [0, 0, 1, 2, 3];

alert(arr.indexOf(0, arr.indexOf(0) + 1)); // to get the index of second zero
Tushar
  • 85,780
  • 21
  • 159
  • 179
2

To get all the indexes of a value you could use the Array.prototype.reduce function to return an array of all indexes that match.

function indexAll(array, match){
    return array.reduce(function(inds,val,i){
        if(val == match) inds.push(i);
        return inds;
    },[]);
}
//  indexAll([0,1,2,3,2,3,2,1,0], 2)   will be [2, 4, 6]
//  indexAll([0,1,2,3,2,3,2,1,0], 4)   will be []
//  indexAll([0,1,2,3,2,3,2,1,0], 0)   will be [0, 8]

But for the use you are looking for it might be better to work on a copy of the array and then delete the items that have been used.

function pairwise(arr, arg) {
  var indexSum=0;
  var arrCopy = arr.slice(0);    // copy of array to modify
  var len=arr.length;            // cached for performance
  for (var i = 0; i < len ; i++) {
    if( arrCopy[i] !== undefined){  //only check if index has not been used 
  //  var j =arrCopy.indexOf(arg -arrCopy[i]);
  //  if(j > -1 && i != j){
  //    sumIndex += i + j;  // add the indexes
  //    delete arrCopy[i];  // delete indexes
  //    delete arrCopy[j];
  //  }  
      for(var j = i+1; j < len; j++){
        if (arrCopy[j] !== undefined) {
          if (arrCopy[i]+arrCopy[j] == arg){
            indexSum += i + j;  // add the indexes
            delete arrCopy[j];  // sets arrCopy[j] to undefined to stop reuse
            j = len;         //jump to next i value
          }
        }
      }
    }
  } 
  return indexSum
}

Instead of using indexOf I used a nested for loop since for loops are generally faster. the indexOf implementation is commented out. see indexOf vs. for loop

Community
  • 1
  • 1
Dean Brown
  • 156
  • 4