5

I have a dictionary like:

a = {"staticData":['----','Blue','Green'], "inData":['Indatahere','----','----']}

How can I find that if the dictionary contains "----", in any of the key's values.
Any Javascript function?
EDIT: What if the case is like this?

a = {"staticData":[], "inData":['Indatahere','----','----']}

It's giving this Error:

TypeError: a[elem].indexOf is not a function
MHS
  • 2,260
  • 11
  • 31
  • 45

4 Answers4

2

Here is the code:

var a = {"staticData":['----','Blue','Green'], "inData":['Indatahere','----','----']};

for(var key in a){
    var value = a[key];
    for(var i=0; i<value.length; i++){
        if(value[i] == '----') alert("Found '----' in '" + key + "' at index " + i);
    };
}

EDIT: Changed iteration over array to normal way after comment.

ElmoVanKielmo
  • 10,907
  • 2
  • 32
  • 46
  • You're just badly reimplementing `indexOf`. Badly, because it's a bad idea to use `for..in` to iterate over arrays. – Florian Margaine Jul 10 '13 at 10:23
  • @FlorianMargaine, I've updated my code after your comment. Please note that `indexOf` returns the first occurence only, so my snippet isn't reimplementation of `indexOf`. It's of course possible to implement all occurencies lookup with `indexOf` but the second `for loop` would be required as well, despite it would look different. Since we iterate over `value` list, the index is already on the plate. – ElmoVanKielmo Jul 10 '13 at 10:30
2

Use indexOf to search each array in the a object:

for (elem in a)
{
    if (a[elem].indexOf("----") != -1)
       alert('---- found at ' + a[elem]);
}

EDIT For this error: TypeError: a[elem].indexOf is not a function the browser possibly considers an empty element to be a non-string type; non-string type does not have an indexOf method.

This code checks the length of the array element (if the element is empty before interpreting the indexOf function.

for (elem in a)
{
    if (a[elem].length > 0 && a[elem].indexOf("----") != -1)
       alert('---- found at ' + a[elem]);
}

If you wish to support IE < 9, see this post to conditionally add a indexOf definition to the Array object. The post also mentions a Jquery alternative.

The SO post mentioned above lists this Mozilla version of indexOf function.

if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt /*, from*/)
  {
    var len = this.length >>> 0;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;

    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}
Community
  • 1
  • 1
suspectus
  • 16,548
  • 8
  • 49
  • 57
  • Good one, so +1 for you. What do you think about mine stackoverflow.com/questions/17567925/javascript-how-to-check-for-specific-string-in-a-dictionary/17568064#answer-17568064 ? – ElmoVanKielmo Jul 10 '13 at 10:21
  • 1
    It's worth to say that `Array.prototype.indexOf` not implemented in IE < 9. If you need to support old versions, you'll need to shim this function. See [this article](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) – Tommi Jul 10 '13 at 11:19
  • @Tommi thanks for the info, post updated with the relevant SO link. – suspectus Jul 10 '13 at 11:41
  • @suspectus: Please check the updated question and help me out! – MHS Jul 10 '13 at 13:57
  • @MHS you must be using IE then? If so you will need to add the code listed (taken from another SO post) at the top of your script. – suspectus Jul 10 '13 at 15:25
1

If you know exactly the nesting level of your value, then a quick solution (as suggested in other answers) is possible.

However, if you need a deep traversal search, you're gonna need a recursive version of the solutions, something like:

function FindTraverse(data, match)
{
    for (var prop in data)
    {
         if (!data.hasOwnProperty(prop)) continue;
         if (data[prop] == match) return true;
         if (typeof data[prop] == 'object' && FindTraverse(data[prop], match)) return true;
    }

    return false;
}

Examples:

FindTraverse({a:'Foo',b:'Bar'}, 'Bar') // true
FindTraverse(['Foo','Bar'], 'Bar') // true
FindTraverse([{name:'Foo'},{name:'Bar'}], 'Bar') // true
FindTraverse({a:{name:'FooBar'},b:'Bar'}, 'FooBar') // true

However, if you're looking for a more thorough solution, use a framework like jsTraverse

haim770
  • 48,394
  • 7
  • 105
  • 133
0

Use Object.getOwnPropertyNames().

You have to write two nested loops. With Object.getOwnPropertyNames you are accessing an array which consists of property names of an object. You will then need to loop over the value of those properties and identify the correct element within this second array.

a = {"staticData":['----','Blue','Green'], "inData":['Indatahere','----','----']}

props = Object.getOwnPropertyNames(a);

for (i=0;i < props.length;i ++) {
    for (z = 0; z < a[props[i]].length; z ++) {
        //console.log(a[props[i]][z])
        if ( (a[props[i]][z]) == '----') {
            console.log("I have found an item with ----")
        };
    }
}
Pawel Miech
  • 7,742
  • 4
  • 36
  • 57