0

I have the following object structure:

var mapData = 
{
   Summary:
   {
      ReportName: 'Month End Report'
   },
   NortheastRegion:
   {
      Property1: 123,
      RegionName: 'Northeast'
   },
   SoutheastRegion:
   {
      Property1: 456,
      RegionName: 'Southeast'   
   },   
}

I want to write a grep function that returns an array of region names. The following function is not returning any values:

var regions = $.grep(mapData, function(n,i)
{
   return n.RegionName;
});

What am I missing here?

Liam
  • 27,717
  • 28
  • 128
  • 190
Jim Platts
  • 25
  • 6

5 Answers5

4

$.grep is for filtering arrays. Your structure isn't an array. $.grep is also just for filtering, but you're talking about both filtering (leaving out Summary) and mapping (getting just the region names).

Instead, you can use

  • Object.keys and push:

    var regions = [];
    Object.keys(mapData).forEach(function(key) {
        var entry = mapData[key];
        if (entry && entry.RegionName) {
            regions.push(entry.RegionName);
        }
    });
    
  • Object.keys, filter, and map:

    var regions = Object.keys(mapData)
        .filter(function(key) {
            return !!mapData[key].RegionName;
        })
        .map(function(key) {
            return mapData[key].RegionName;
        });
    
  • A for-in loop and push:

    var regions = [];
    for (var key in mapData) {
         if (mapData.hasOwnProperty(key)) {
             var entry = mapData[key];
             if (entry && entry.RegionName) {
                 regions.push(entry.RegionName);
             }
         }
    }
    

...probably others.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

That's an object, not an array. According to the jQuery docs, your above example would work if mapData were an array.

You can use lodash's mapValues for this type of thing:

var regions = _.mapValues(mapData, function(o) {
  return o.RegionName;
});

ES6:

const regions = _.mapValues(mapData, o => o.RegionName)
Josh Beam
  • 19,292
  • 3
  • 45
  • 68
1

As stated in jQuery.grep() docs, you should pass an array as data to be searched, but mapData is an object. However, you can loop through the object keys with Object.keys(), but AFAIK you'll have to use function specific for your case, like:

var mapData = 
{
   Summary:
   {
      ReportName: 'Month End Report'
   },
   NortheastRegion:
   {
      Property1: 123,
      RegionName: 'Northeast'
   },
   SoutheastRegion:
   {
      Property1: 456,
      RegionName: 'Southeast'   
   },   
};

var keys = Object.keys(mapData),
    result = [];

console.log(keys);

keys.forEach(function(key) {
  var region = mapData[key].RegionName;
  
  if (region && result.indexOf(region) == -1) {
    result.push(region);
  }
});

console.log(result);

// Short version - based on @KooiInc answer
console.log(
  Object.keys(mapData).map(m => mapData[m].RegionName).filter(m => m)
);
DontVoteMeDown
  • 21,122
  • 10
  • 69
  • 105
1

$.grep is used for arrays. mapData is an object. You could try using map/filter for the keys of mapData, something like:

var mapData = 
{
   Summary:
   {
      ReportName: 'Month End Report'
   },
   NortheastRegion:
   {
      Property1: 123,
      RegionName: 'Northeast'
   },
   SoutheastRegion:
   {
      Property1: 456,
      RegionName: 'Southeast'   
   },   
};

var regionNames = Object.keys(mapData)
 .map( function (key) { return mapData[key].RegionName; } )
 .filter( function (name) { return name; } );
console.dir(regionNames);

// es2105 
var regionNames2 = Object.keys(mapData)
 .map( key => mapData[key].RegionName  )
 .filter( name => name );
console.dir(regionNames2);
KooiInc
  • 119,216
  • 31
  • 141
  • 177
0

Just turn $.grep to $.map and you would good to go.

var regions = $.map(mapData, function(n,i)
{
   return n.RegionName;
});
Ramin
  • 473
  • 1
  • 5
  • 15