20

I'm using map with a list of Cheerio results to return an attribute value. What I want is a variable that contains a list of attribute values (in this case ID's), but instead I'm getting the ID's and extra data.

The following code prints a list of ID's:

let ids = $('[data-profileid]').map(function() {
    console.log($(this).attr('data-profileid'))
})

Result:

1012938412
493240324
123948532
423948234
...

But, the following code returns the IDs but in a different format:

let ids = $('[data-profileid]').map(function() {
    return $(this).attr('data-profileid')
})

console.log(ids)

Results:

...
'69': '234234234,
'70': '9328402397432',
'71': '1324235234',
  options:
   { withDomLvl1: true,
     normalizeWhitespace: false,
     xmlMode: false,
     decodeEntities: true },
  _root:
   { '0':
      { type: 'root',
        name: 'root',
        attribs: {},
...

What is all this extra data? It certainly isn't required. I'd rather just have an ordinary array.

BugHunterUK
  • 8,346
  • 16
  • 65
  • 121

2 Answers2

35

According to http://api.jquery.com/map/:

As the return value is a jQuery object, which contains an array, it's very common to call .get() on the result to work with a basic array.

So it looks like this should work:

let ids = $('[data-profileid]').map(function() {
    return $(this).attr('data-profileid')
}).get()
3ch01c
  • 2,336
  • 2
  • 17
  • 15
  • But why is the map function not passed the node on the parameter!!!!??? – Robert Moskal Jul 22 '18 at 01:48
  • @RobertMoskal I think you're thinking of [jQuery.map()](http://api.jquery.com/jquery.map/) which takes an array as a parameter. This is using the object's (i.e., a set matched by a jQuery selector) [.map()](http://api.jquery.com/map/). Check the links for a more detailed explanation. – 3ch01c Dec 08 '18 at 00:14
8

What is all this extra data? It certainly isn't required. I'd rather just have an ordinary array.

Cheerio has a fluent API, meaning most of its functions return an object on which additional functions can be chained. If map just returned an "ordinary array" then you wouldn't be able to call additional Cheerio functions on the result. There aren't a lot of ways you can chain additional function calls onto the result of your map call, which returns an array of strings, but Cheerio's developers (taking a cue from jQuery's developers) chose to keep a consistent API rather than pepper it with special cases.

If you want an ordinary array, though, Cheerio gives you a handy toArray function:

let ids = $('[data-profileid]').map(function() {
  return $(this).attr('data-profileid')
});

console.log(ids.toArray());
// => [ '1012938412', '493240324', '123948532', '423948234' ]
Jordan Running
  • 102,619
  • 17
  • 182
  • 182