goog.array.map how to skip an item on certain condition?

263 views
Skip to first unread message

dipa...@google.com

unread,
May 5, 2014, 5:32:21 PM5/5/14
to closure-lib...@googlegroups.com
I am trying to use goog.array.map to loop through an "items" array and want to return only items in "processedItems" array for certain condition as shown below:

  var processedItems = goog.array.map(items, function(item) {
    if (item.id < 0) {
      return {
        id: item.id,
        n: item.name,
        w: item.width * 100,
        h: item.height * 100,
        r: item.r * 100,
        u: item.unit / 100
      };
    }
  });

When I run the code which few records with item.id value < 0, instead of skipping the item in resulting array, it adds "undefined" as an item.
I also tried to use "else" condition to "return;" but still it would return something when condition does not match.

Is there a way around or I have to use goog.array.forEach() which has more control over the loop?

Thanks.



Ilia Mirkin

unread,
May 6, 2014, 11:54:08 AM5/6/14
to closure-lib...@googlegroups.com
map can't filter. To filter, you need to use filter :) (goog.array.filter)

So you might do

var processed = goog.array.map(goog.array.filter(items, function (x) {
return x.id < 0 }), function (item) {
return { ... }
}

-ilia

>
> Thanks.
>
>
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "Closure Library Discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to closure-library-d...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Paul Draper

unread,
Jul 9, 2014, 3:48:42 AM7/9/14
to closure-lib...@googlegroups.com, imi...@alum.mit.edu
I've used done one of three things.

1) filter and then map (Illa's example)

2) Create a new array and then inside a forEach, append to it.

3) I wrote a flatMap function I use sometimes

array.flatMap = function(array, f, self) {
  var results = [];
  goog.array.forEach(array, function(elem, i, array) {
    goog.array.extend(results, f.call(this, elem, i, array));
  }, self);
};

You would use it like

var processedItems = array.flatMap(items, function(item) {
    if (item.id < 0) {
      return [{
        id: item.id,
        n: item.name,
        w: item.width * 100,
        h: item.height * 100,
        r: item.r * 100,
        u: item.unit / 100
      }];
    } else {
      return [];
    }
  });

If you are familiar with flatMap in other languages, you'll recognize that you can do more than just filter, though.

I haven't tested them but in order of increasing performance, I'd guess #3 #1 #2, and readability in reverse order.

Tyler Breisacher

unread,
Jul 10, 2014, 1:21:50 AM7/10/14
to closure-lib...@googlegroups.com, imi...@alum.mit.edu
+1 to "map then filter" If you're doing this, you might prefer the built-in functions instead of the goog.* ones. So this would become:

var processed = items.filter(function (x) { return x.id < 0; }).map(function (item) { return { ... } });

which I like because it's less noisy and reads "in the right order" (first filter, then map). Caveats:

1. The built-in map and filter functions aren't in all browsers. IE 8 and below don't have them, according to MDN.
2. goog.array.* functions work on most "array like" objects, but Array methods (of course) only work on real Arrays.
Reply all
Reply to author
Forward
0 new messages