2

I'm having a hard time understanding the behaviour of jQuery's .toArray() in this scenario.

I have 2 <table>, one for "Participants" and one for "Winners". I want to extract some data from these tables using jQuery.

I use 2 .map() functions to transform the contents of the table into arrays/objects, have a look at the code:

HTML:

<h2>Participants</h2>
<table border="1">
  <tbody>
    <tr>
      <td>01</td>
      <td>Andrew</td>
    </tr>
    <tr>
      <td>02</td>
      <td>Julian</td>
    </tr>
    <tr>
      <td>03</td>
      <td>Matt</td>
    </tr>
    <tr>
      <td>04</td>
      <td>Sarah</td>
    </tr>
  </tbody>
</table>

<h2>Winners</h2>
<table border="1">
  <tbody>
    <tr>
      <td>01</td>
      <td>Andrew</td>
    </tr>
    <tr>
      <td>04</td>
      <td>Sarah</td>
    </tr>
  </tbody>
</table>

JavaScript:

const result = $('table')
  .map((i, table) => {
    return $(table)
      .find('tbody tr')
      .map((j, row) => {
        const $row = $(row);

        return {
          number: $row.find('td:nth-child(1)').text(),
          name: $row.find('td:nth-child(2)').text(),
        };
      })
      .toArray(); // [1]
  })
  .toArray();

console.log(result);

[1] Without the .toArray() I get an array with 2 jQuery objects, one for each table. (Great!)
But when I add .toArray() all of a sudden it returns a single array with all the objects inside, why?
Where's the separation the was there before?!

Expected output:

[
  [
    {number: "01", name: "Andrew"},
    {number: "02", name: "Julian"},
    {number: "03", name: "Matt"},
    {number: "04", name: "Sarah"}
  ],
  [
    {number: "01", name: "Andrew"},
    {number: "04", name: "Sarah"}
  ]
]

Actual output:

[
  {number: "01", name: "Andrew"},
  {number: "02", name: "Julian"},
  {number: "03", name: "Matt"},
  {number: "04", name: "Sarah"},
  {number: "01", name: "Andrew"},
  {number: "04", name: "Sarah"}
]

I made a jsfiddle so you can see for yourself: https://jsfiddle.net/93cLyq6h/22/

2 Answers 2

1

Your issue is actually not with .toArray() but with jquery's .map(). Here is another answer explaining this, but when the .map() parameter function returns an array, each element is inserted into the set rather than the array itself. So your outer .map() flattens the two arrays into one.

If an array is returned, the elements inside the array are inserted into the set.

Is there a jQuery map utility that doesn't automically flatten? here is something that should help you get what you're looking for.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot, i really don't understand the design decision behind this behaviour, but at least now i know about it!
0

The results of the $.fn.map call needs to be wrapped in square brackets [ ... ].

const result = $('table')
  .map((i, table) => [
    $(table)
      .find('tbody tr')
      .map((j, row) => [{
        number: $(row).find('td:nth-child(1)').text(),
        name: $(row).find('td:nth-child(2)').text(),
      }]).toArray()
  ]).toArray();

// Format results...
console.log(JSON.stringify(result, null, 2)
  .replace(/\{\n\s+"/g, '{ "')
  .replace(/,\n\s+"/g, ', ')
  .replace(/"\n\s+\}/g, '" }'));
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h2>Participants</h2>
<table border="1">
  <tbody>
    <tr>
      <td>01</td>
      <td>Andrew</td>
    </tr>
    <tr>
      <td>02</td>
      <td>Julian</td>
    </tr>
    <tr>
      <td>03</td>
      <td>Matt</td>
    </tr>
    <tr>
      <td>04</td>
      <td>Sarah</td>
    </tr>
  </tbody>
</table>

<h2>Winners</h2>
<table border="1">
  <tbody>
    <tr>
      <td>01</td>
      <td>Andrew</td>
    </tr>
    <tr>
      <td>04</td>
      <td>Sarah</td>
    </tr>
  </tbody>
</table>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.