0

I am sure this is really simple, I used to have a function for checking the contents of an array. Now Id like to modify it to check a two dimensional array.

function ChkArray(Str, Val){

for (var i=0;i<Str.length;i++){
        if (Str[i] == Val) {return i;}
    }
return -1;
}

My new attempt:

function ChkArray2(Str, Val){

for (var i=0;i<Str.length;i++){
        for (var ii=0;ii<Str[ii].length;ii++){
            if (Str[i][ii] == Val) {return i;}
        }
    }
return -1;
}
Mark
  • 5,423
  • 11
  • 47
  • 62
  • I realised that I have another problem, the keys my two dimensional arrays are not in fact numbers. Is there a 'foreach' style loop like php? – Mark Dec 08 '09 at 13:51

3 Answers3

2

Close, in your inner loop, you want to check the length of the current item in the outer loop:

function ChkArray2(Str, Val){

    for (var i=0;i<Str.length;i++){
        for (var ii=0;ii<Str[i].length;ii++){
            if (Str[i][ii] == Val) {return i;}
        }
    }
    return -1;
}

that should work

David Hedlund
  • 128,221
  • 31
  • 203
  • 222
  • Thank you, it does... except I realised that I have another problem, the keys my two dimensional arrays are not in fact numbers. Is there a 'foreach' style loop like php? – Mark Dec 08 '09 at 13:52
  • Yes there is: the for...in loop. http://stackoverflow.com/questions/684672/loop-through-json-object – Tim Down Dec 08 '09 at 13:56
  • yep, and it should only ever be used on objects, not arrays. – nickf Dec 08 '09 at 14:06
  • If you're using non-integer keys, what you've got is an Object map and not an Array. You can use Array like an Object, but it's not at all a good idea. – bobince Dec 08 '09 at 14:07
1

If you're asking about better ways to tackle the problem, I would perhaps think about writing a function which can work with any number of dimensions in the array. In your example, the return value is the index of the top level array, but to make it generic, you would have to return the full "path" to the found element, and let the calling code decide what information it wants:

    function multiFind(arr, val) {  // please don't name an array "str"!
    for (var i = 0, l = arr.length; i < l; ++i) {
        if (arr[i] === val) {
            return [i];
        } else if (is_array(arr[i])) {
            var ret = multiFind(arr[i], val);
            if (ret !== false) {
                ret.unshift(i);
                return ret;
            }

        }
    }
    return false;
}

// this function by Doug Crockford
var is_array = function (value) {
    return value &&
        typeof value === 'object' &&
        typeof value.length === 'number' &&
        typeof value.splice === 'function' &&
        !(value.propertyIsEnumerable('length'));
};

var inp = ["a","b",["c", ["d", "e", ["f", "g"], "h"]]];

multiFind(inp, "a"); // [0]
multiFind(inp, "b"); // [1]
multiFind(inp, "c"); // [2, 0]
multiFind(inp, "f"); // [2, 1, 2, 0]
multiFind(inp, "h"); // [2, 1, 3]
multiFind(inp, "x"); // false
nickf
  • 537,072
  • 198
  • 649
  • 721
-1

I suggest using javascript foreach.

function ChkArray2(Str, Val){    
    for (var i in Str){
        for (var ii in Str[i]){
            if (Str[i][ii] == Val){
                return i;
            }
        }
    }
    return -1;
}
Li0liQ
  • 11,158
  • 35
  • 52
  • 3
    this is a very bad idea. You should never use `for .. in` to iterate arrays, since it will include all properties of the array, which will (at the very least) include "length". – nickf Dec 08 '09 at 14:00
  • @nickf You are right, although for this particular issue this is an acceptable solution. – Li0liQ Dec 08 '09 at 14:06
  • 1
    for...in over Array is a common mistake. As well as the properties problem, you also won't necessarily get the items in numerical order. – bobince Dec 08 '09 at 14:08
  • @bobince Author pointed out that keys are not numbers therefore there cannot be any "numerical" order;). Please, read the whole story before minusing :) – Li0liQ Dec 08 '09 at 14:09