Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Continue 2 levels deep in JS

Consider this very simple code:

someLabel:
for (var i=0; i<newFonts.length; i++) {
    var newFont = newFonts[i];

    for (var j=0; j<oldFonts.length; j++) {
        var oldFont = oldFonts[j];

        if (fb.equals(oldFont, newFont)) {
            // Break out of inner loop, don't finish outer iteration, continue with next outer item
            continue 2;
        }
    }

    // This must only happen if `newFont` doesn't match ANY `oldFonts`
    oldFonts.push(newFont);
}

What it's supposed to do is compare all oldFonts objects with newFonts objects and only add newFont to oldFonts (oldFonts.push) if it doesn't already exist (fb.equals).

oldFonts and newFonts are objects with name and host properties. Both are used in fb.equals() to determine equality. indexOf() won't work.

This is exactly how I'd do it in PHP. It doesn't work in JS, because JS doesn't support continue 2, which means continue 2 levels.

How do I do this in JS??

  • continue wont do, because it'll still finish the inner loop and end up at the push
  • break won't do, because it'll skip the inner loop and jump straight to the push
  • break someLabel won't do, because I don't want to skip ALL newFonts when ONE must be ignored

This must be possible without a single function...

like image 262
Rudie Avatar asked Jun 23 '26 22:06

Rudie


1 Answers

The comments demonstrated how to continue to a labeled statement. But as to your original problem, you might be able to solve it more easily:

var difference = function(x, y) {
    return x.filter(function(e) {return y.indexOf(e) < 0;});
};

// or oldFonts = ... if you prefer to mutate
var combinedFonts = oldFonts.concat(difference(newFonts, oldFonts));

Update

If the requirement for testing equality is more sophisticated, as noted in the comments, then something slightly more is needed. To my mind, this is still simpler than the original approach with labeled loops:

var complement = function(pred, a, b) {
    return a.filter(function(x) {
        return !b.some(function(y) {return pred(x, y);});
    });
};

var sameName = function(a, b) {return a.name === b.name;};

var combinedFonts = oldFonts.concat(complement(sameName, newFonts, oldFonts));

You can see this on JSFiddle


I can't wait for fat-arrows to be widely available. Here's the equivalent:

var complement = (pred, a, b) => a.filter(x => !b.some(y => pred(x, y)));
var sameName = (a, b) => a.name === b.name;
like image 162
Scott Sauyet Avatar answered Jun 26 '26 12:06

Scott Sauyet



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!