5

Disclaimer: This question is NOT as same as this one.

I have an example of nested array:

var testArray = [
  true,
  "",
  [
    1,
    {a: 2, b: [3, false]},
    [2, []],
    null
  ],
  4,
  undefined,
  [5, "test"],
  function() {}
];

How to get indexOf of a value in nested array, like:

testArray.multiIndexOf(null); //Expected result will be [2, 3]

I will explain what is happening here.

First, we break down testArray to this:

var testArrayExplain = [0, 1, [0, 1, [0, 1], 3], 3, 4, [0, 1], 6];

As you can see here, this array is as much same as above: first layer of array have length of 7, then take a look at value at location #2, we will see another array being nested to first one. As you can remember from above, that null value have the same exact location as location #3 in array at location #2 of first array

So we will have first layer location then second layer location of null: [2, 3], stored in array sorted from first layer to last layer.

Another example:

var testArrayTwo = [1,[2,3,4],5,[6,[7,8],9,10],11,12];
testArrayTwo.multiIndexOf(6); //return [3, 0]

Optional: If an nested array have two same values, then get location of first value, or an array stored both two location? And if value is not in nested array, return -1 like indexOf?

Am I asking too much? And is this question is important for future developers?

Community
  • 1
  • 1
Trung0246
  • 689
  • 1
  • 10
  • 21

3 Answers3

8

You could iterate the array and stop if the wanted item is found. If possible have a look for nested arrays and proceed.

Array.prototype.multiIndexOf = function (value) {
    var result;
    this.some(function iter(path) {
        return function (a, i) {
            if (a === value) {
                result = path.concat(i);                        
                return true;
            };
            return Array.isArray(a) && a.some(iter(path.concat(i)));
        }
    }([]));
    return result;
}

var testArray = [true, "", [1, { a: 2, b: [3, false] }, [2, []], null], 4, undefined, [5, "test"], function () { }];

console.log(testArray.multiIndexOf(null));
console.log([1, [2, 3, 4], 5, [6, [7, 8], 9, 10], 11, 12].multiIndexOf(6));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • 1
    Damn Nina, you never cease to amaze me. Have you got any suggested resources to get that good. – synthet1c Oct 08 '16 at 07:57
  • @Nina Could you please explain your code in depth . I am a complete beginner in Java script . Thank you – RajGopalbh4 Mar 02 '21 at 12:17
  • @RajGopalbh4, it is a bit more complicated, but you can start by having a look to [`Array#some`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some) and [How do JavaScript closures work?](https://stackoverflow.com/q/111102/1447675). – Nina Scholz Mar 02 '21 at 12:25
  • @Nina . That's fine . I wrote my own logic in core java . I had spent around 2 days to solve this problem in my own way .This is just another way to solve the problem . Here is my java code . Ignore the first 0 in output . [Javacode](https://drive.google.com/file/d/18gG90hnGcB6fFnEMYjCd2wUmDG8hMxVZ/view?usp=sharing) – RajGopalbh4 Mar 04 '21 at 06:14
2

An alternate to @Nina's answer.

As an additional check, I have added

JSON.stringify(array[key]).indexOf(searchVal) > -1

This will ignore a tree of recursion if value is not available.

var testArray = [1, [2, 3, 4], 5, [6, [7, 8], 9, 10], 11, 12]

function findIndex(array, searchVal, pindex) {
  var result = -1;
  var index = -1;
  for (var key in array) {
    index++;
    if (typeof(array[key]) === "object" &&
      JSON.stringify(array[key]).indexOf(searchVal) > -1 &&
      findIndex(array[key], searchVal, index) !== -1) {
      result = index;
      break;
    } else if (typeof(item) !== "object" && array[key] === searchVal) {
      result = index;
      break;
    }
  }
  return pindex || result;
}
var r1 = findIndex(testArray, 2);
var r2 = findIndex(testArray, 3);
var r3 = findIndex(testArray, 8);
console.log("Result: ", r1, r2, r3)
Community
  • 1
  • 1
Rajesh
  • 24,354
  • 5
  • 48
  • 79
0

You can accomplish your goal using the following function. It allows you to use deepIndexOf the same way, as you use indexOf on an array:

[1,[5,[2,"abc"]],3,4].deepIndexOf("abc")    //returns [1,1,1]
[1,[5,[2,"abc"]],3,4].deepIndexOf("none")    //returns -1

It however doesn't work for arrays yet. It's easily expendable however.

Array.prototype.deepIndexOf = function (val) {
  for (var i=0; i<this.length; i++) {
    if(this[i] == val)
      return [i];
    var insideIndex = this[i].deepIndexOf ?
            this[i].deepIndexOf(val) : -1;
    if (insideIndex != -1)
       return [i].concat(insideIndex);
  }
  return -1;
}

document.write([1,[5,[2,"abc"]],3,4].deepIndexOf("abc")
               +"<br>");
document.write([1,[5,[2,"abc"]],3,4].deepIndexOf("none"));
Syntac
  • 1,687
  • 11
  • 10