2

I am wanting to concatenate strings from 2 separate elements and have them stored in a variable.

Currently my code is setting the variable equal to: "Daily: 1070300, Weekly: 1070300, Monthly: 1070300"

My goal is to make the variable in the console equal to: "Daily: 10, Weekly: 70, Monthly: 300"

      $(document).ready(function() {
        var str = '';
        $('tbody > tr').each(function() {
          $(this).find('.key').each(function() {
            str += $(this).text() + ": " + $(this).parents().siblings('tr').find('.value').text() + ", ";
          })
        });
        console.log(str);
      });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <tbody>
    <tr>
      <th class="key">Daily</th>
      <th class="key">Weekly</th>
      <th class="key">Monthly</th>
    </tr>
    <tr>
      <td class="value">10</td>
      <td class="value">70</td>
      <td class="value">300</td>
    </tr>
  </tbody>
</table>

Thank you for your help all!

2
  • because you are reading all of the tds text at once, not the one for the column you are after. Commented Apr 10, 2018 at 20:45
  • what do you want output if there is more than 1 row of values? Just the first row, or one console.log for each row of values? Commented Apr 10, 2018 at 20:51

4 Answers 4

5

Each time through the key loop, you're grabbing the content of all three value cells (since $(this).parents().siblings('tr').find('.value') matches all three). There are many ways to fix this but one easy one I see is to use the index argument on the inner loop to select the value cell corresponding to the current key (using jQuery's eq function):

  $(document).ready(function() {
    var str = '';
    $('tbody > tr').each(function() {
      $(this).find('.key').each(function(index) {
        str += $(this).text() + ": " + $(this).parents().siblings('tr').find('.value').eq(index).text() + ", ";
      })
    });
    console.log(str);
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
    <tbody>
        <tr>
      <th class="key">Daily</th>
            <th class="key">Weekly</th>
            <th class="key">Monthly</th>
        </tr>
        <tr>
            <td class="value">10</td>
            <td class="value">70</td>
            <td class="value">300</td>
        </tr>
    </tbody>
</table>

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

3 Comments

The code works based on what OP did, but it is very inefficient.
What would make more sense @epascarello ?
Thank you for your answer @nvioli ! Is there a way to grab and combine the 2 values simultaneously so it is more efficient? Just wondering if my code is not optimal.
1

The code is very inefficient when you keep looking up stuff in the loop. So fixing it to read the index would work, it just causes the code to do more work than needed.

How can it be improved. Look up the two rows and one loop using the indexes.

var keys = $("table .key")  //select the keys
var values = $("table .value")  //select the values

var items = []  // place to store the pairs
keys.each(function(index, elem){ //loop over the keys
   items.push(elem.textContent + " : " +  values[index].textContent)  // read the text and use the index to get the value
})
console.log(items.join(", "))  // build your final string by joing the array together
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
    <tbody>
        <tr>
            <th class="key">Daily</th>
            <th class="key">Weekly</th>
            <th class="key">Monthly</th>
        </tr>
        <tr>
            <td class="value">10</td>
            <td class="value">70</td>
            <td class="value">300</td>
        </tr>
    </tbody>
</table>

1 Comment

Thank you for the answer @epascarello ! I learned a lot from it.
1

Collect the .key and .value classes into a NodeList convert the NodeList into arrays. Then merge the 2 arrays into key/value pairs stored in an Object Literal. Finally convert the object into a string so it can be displayed.

Demo

Details are commented in Demo

// Collect all th.key into a NodeList and turn it into an array 
var keys = Array.from(document.querySelectorAll('.key'));
// As above with all td.value
var vals = Array.from(document.querySelectorAll('.value'));

function kvMerge(arr1, arr2) {
  // Declare empty arrays and an object literal
  var K = [];
  var V = [];
  var entries = {};
  
  /* map the first array...
  || Extract text out of the arrays
  || Push text into a new array
  || Then assign each of the key/value pairs to the object
  */
  arr1.map(function(n1, idx) {
    var txt1 = n1.textContent;
    var txt2 = arr2[idx].textContent;
    K.push(txt1);
    V.push(txt2);
    entries[K[idx]] = V[idx];
  });
  return entries;
}

var result = kvMerge(keys, vals);
console.log(result);

// Reference the display area
var view = document.querySelector('.display');
// Change entries object into a string
var text = JSON.stringify(result);
// Clean up the text
var final = text.replace(/[{"}]{1,}/g, ``);
// Display the text
view.textContent = final
<table>
  <tbody>
    <tr>
      <th class="key">Daily</th>
      <th class="key">Weekly</th>
      <th class="key">Monthly</th>
    </tr>
    <tr>
      <td class="value">10</td>
      <td class="value">70</td>
      <td class="value">300</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td class='display' colspan='3'></td>
    </tr>
  </tfoot>
</table>

Comments

0

You can also solve that using unique ids, like that:

$(document).ready(function() {
  var str = '';
  $('tbody > tr').each(function() {
    $(this).find('.key').each(function() {
      var index = $(this).attr('id').slice(3)
      str += $(this).text() + ": " + $('#value'+index).text() + ", ";
    })
  });
  console.log(str);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <tbody>
    <tr>
      <th class="key" id="key1">Daily</th>
      <th class="key" id="key2">Weekly</th>
      <th class="key" id="key3">Monthly</th>
    </tr>
    <tr>
      <td class="value" id="value1">10</td>
      <td class="value" id="value2">70</td>
      <td class="value" id="value3">300</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.