0

Given a JS as follows:

for (c in chars) {
    for (i in data) {
        if (data[i].item === chars[c]) {
            // do my stuff;
        }
        else { /* do something else */}
    }
}

and data such:

var chars = [ 'A', 'B', 'C', 'A', 'C' ];
var data = [
    {'item':'A', 'rank': '1'}, 
    {'item':'B', 'rank': '2'}, 
    {'item':'C', 'rank': '3'}
    // no duplicate
];

Is there a simpler syntax to express that rather than nested for loops and inner conditions?

I try to match two datasets, more precisely to use chars's keys to iterate data and find values.

20
  • 3
    Wait, are you trying to iterate over an array with for in? Commented Jul 20, 2013 at 22:34
  • @acdcjunior It works. Just remember that the iteration variable is set to the indexes, not the values (it's not like PHP foreach). Commented Jul 20, 2013 at 22:35
  • 2
    @Barmar What works? The for in for arrays? If so, I'm not saying it doesn't, I'm say one shouldn't, as it can screw your code up. Commented Jul 20, 2013 at 22:37
  • 1
    ...or like this: jsfiddle.net/bysBH/7 Commented Jul 20, 2013 at 23:00
  • 1
    @Hugolpz: Yeah, I think your nested loops are about as simple as they can get. In this specific case, a key/value map is definitely the way to go. Will be faster too. Commented Jul 21, 2013 at 19:31

3 Answers 3

1

You could do this:

for (i = 0; i < data.length; i++) {
    if (chars.indexOf(data[i].item) != -1) {
        // Do something
    } else {
        // Do something else
    }
}

However, if chars is large, I would create an object whose keys are the elements of chars and use if (chars_obj[data[i].item]). This is more efficient than searching an array every time.

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

3 Comments

with a sidenote: Array.indexOf isn't supported in older browsers.
I don't know what OP specifically needs, but this will be a little different if there's more than one of the same letter in the chars Array.
@Barmar this is not what the OP wants. With the OP example, 15 functions are executed (either my stuff or something else).
1

An alternative to simplifying the code would be to encapsulate and abstract it away into a utility that accepts callbacks, than reuse that whenever needed, like so:

// definition
function eachChar(onMatch, onMismatch) {
    for (c in chars) {
        for (i in data) {
            if (data[i].item === chars[c]) {
                typeof onMatch === 'function' && onMatch(); 
            } else {
                typeof onMismatch === 'function' && onMismatch(); 
            }
        }
    }
}

// usage examples
eachChar(function() {
    // do something when it's a match
});
eachChar(function() {
    // do something when it's a match
}, function() {
    // do something else when it's not
});

See a live demo on jsFiddle.


As a sidenote, you would want to explicitly declare variables used as loop indexes, as to not exposing them in an outer scope (e.g. the global scope):

// that:
for (c in chars) {
    for (i in data) {

// would become this:
for (var c in chars) {
    for (var i in data) {

Comments

0

Since you tagged your question jquery, you could use a jquery solution:

$.each(chars, function (cndx, chr) {
    $.each(data, function (dndx, datum) {
        if (datum.item === chr) {
            // do my stuff;
        } else {
            /* do something else */
        }
    }
});

Not any more succinct, but at least you don't have to index.

2 Comments

It's not really simpler, only camouflage.
Not entirely true -- indexing is often a vector for subtle bugs.

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.