2

The code below outputs all of the p tags with staff-member-title appended

let arr = [];

$("li.staff-directory-department").map((item, index) => {
  arr.push({
    title: $("p.staff-member-title", index).text()
  });
});

console.log(arr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="staff-directory">
  <li class="staff-directory-department">
    <h2 class="staff-directory-department">
      Academic Affairs
    </h2>
    <ul class="staff-directory-department-list">
      <li class="staff-member ">
        <a href="" class="staff-member-image">
          <img src="" />
        </a>
        <h3 class="staff-member-name">
          <a href="">Meli</a>
        </h3>
        <p class="staff-member-title">Director of Institutional Research & Effectiveness</p>
        <p class="staff-member-email">
          <a href="mailto:"></a>
        </p>
        <p class="staff-member-phone"><a href="tel:">(90</a></p>
      </li>
    </ul>
  </li>
</ul>

Current output for arrayInfo:

[
  { title: 'Director of Institutional Research & EffectivenessAdministrative AssistantDirector of Online Learning and Educational TechnologyAssociate Vice President of Academics and Strategic InitiativesVice President for Academics & Student Life' },
  { title: 'Director of Institutional Research & EffectivenessAdministrative AssistantDirector of Online Learning and Educational TechnologyAssociate Vice President of Academics and Strategic InitiativesVice President for Academics & Student Life' },
  ...
]

Expected output:

[
  { title: 'Director of Institutional Research & Effectiveness' },
  { title: 'Administrative Assistant' },
  ...
]
connexo
  • 53,704
  • 14
  • 91
  • 128
  • Your expected output doesn't make sense... is title an array – robinsax Dec 29 '18 at 01:17
  • @robinsax title is a key, the final result should be an array of objects `[ {title: ... } ]` does that help? – themythlegend Dec 29 '18 at 01:22
  • Canonical thread for text joined in Cheerio: [Cheerio: Extract Text from HTML with separators](https://stackoverflow.com/questions/31543451/cheerio-extract-text-from-html-with-separators). – ggorlen Aug 27 '23 at 19:42

2 Answers2

1

You're mixing up the arguments, index comes first in Cheerio.map:

let arr = $('li.staff-directory-department').map((i, el) => {
  return { title: $(el).find('p.staff-member-title').text() }
}).get()

It might be simpler to use Array.map

let arr = $('li.staff-directory-department').get().map((el) => {
  return { title: $(el).find('p.staff-member-title').text() }
})

Note: get() turns the cheerio object into an array.

pguardiario
  • 53,827
  • 19
  • 119
  • 159
  • Question, why is `$('li.staff-directory-department').map` working in the first place if it is an object? Not talking about your code, talking about mine. I don't use `.get()` anywhere. – themythlegend Dec 29 '18 at 03:39
  • Also, is there a way to do `[ {title: [...] } ]` instead of having multiple title objects? – themythlegend Dec 29 '18 at 03:47
  • Because before Arrays had a .map(), jQuery added it, and then Cheerio copied that. You can change title to titles and add another .map() inside there but I only see 1 title in that html. – pguardiario Dec 29 '18 at 03:59
  • The html is a lengthy, I only posted a snippet. Would it be `title: $("p.staff-member-title").map((index, item) => { index.text() })` – themythlegend Dec 29 '18 at 04:09
  • Using `$(el).find()` on each element rather than `$(...)` is critical--otherwise, each query runs from the root of the whole HTML tree rather than inside of each element subtree and explains why you're seeing all nodes' text joined together. This is a good answer, but the explanation is a bit incomplete, missing this key point. – ggorlen Aug 27 '23 at 19:39
-1

I believe your problem is that you're creating a dictionary with Javascript, but giving one key to multiple items, and so when that key is called you're pulling up each item associated with that key.

What you may want to try instead is to put all of the Titles into an array, and then associate that array with the key Title, so that when you call the key Title you can sift through the array of all the Titles.

let arr = [];
let titleArr = [];

$("li.staff-directory-department").map((item, index) => {
  titleArr.push({
    $("p.staff-member-title", index).text()
  });
});

arr.push({title: titleArr});

then when you want to grab the titles just call the array using the key:

for(var x = 0; x < titleArr.length; x++){
    console.log(arr["title"][x]);
}
omoshiroiii
  • 643
  • 5
  • 11
  • interesting thought and I agree. Any suggestions for how I would put all of the information into an array? `[ { title: [ .. ] } ]` – themythlegend Dec 29 '18 at 02:19
  • Updated the post – omoshiroiii Dec 29 '18 at 02:57
  • This doesn't look right at all, wouldn't that code create a nested array? – themythlegend Dec 29 '18 at 03:11
  • This is incorrect for two reasons: (1) it still uses `$(...)` rather than `$(item).find(...)`, so each inner query collects all text from the root of the HTML tree rather than the one element in the subtree and (2) `map` passes `(i, e)` to the callback, not `(e, i)`. It's also poor style because you're ignoring the array `map` allocates. Better to `return` the element from each callback instead of manually creating a separate array and `push`ing to it. – ggorlen Aug 27 '23 at 19:42