Emiel VdV
Emiel VdV

Reputation: 297

How to convert a very large table into a specific javascript array?

I want to make a very large array of data that I found on this website. I copied the large table from that website in to my project:

enter image description here

This is an example of that table:

<tr>
  <td>Acid Rain</td>
  <td>
    rain, smoke / rain, smog / rain, sickness / cloud, smoke / cloud, smog
    / cloud, sickness / rain, city
  </td>
</tr>

I want to convert this table in to a javascript array of objects like this:

[
  {
    name: "Acid Rain",
    elements: [
      ["rain", "smoke"],
      ["rain", "smog"],
      ["rain", "sickness"],
      ["cloud", "smoke"],
      ["cloud", "smog"],
      ["cloud", "sickness"],
      ["rain", "city"],
    ],
  },
  {...},
  {...}
];

The reason I want to convert this is because it would take way too much time to input this by hand.

Upvotes: 0

Views: 137

Answers (4)

Paprika
Paprika

Reputation: 96

You first need to iterate by rows, and then transform them.

You can get rows using table.rows, and iterate by them. To get cells use row.cells. cells[0] - would be row name and cells[1] - would be row elements. You need to split and transform your elements, then add it to result object then array.

const table = document.getElementById("table");
const result = [];

// iterate by rows
for (let i = 1; i < table.rows.length; i++) {
  const row = table.rows[i];
  const rowName = row.cells[0].textContent;
  const rowElements = row.cells[1].textContent;

  result.push({
    name: rowName,
    elements: splitRowElements(rowElements)
  });
}

function splitRowElements(rowElements) {
  const splitedByComma = rowElements.split(",");
  const splitedAlsoBySlash = splitedByComma.map((element) =>
    element.split("/")
  );
  const splitedAndTrimmed = splitedAlsoBySlash.map((element) =>
    element.map((elementOfElement) => elementOfElement.trim())
  );

  return splitedAndTrimmed;
}

I made functioning example on codesandbox:

https://codesandbox.io/s/blissful-feynman-559sw1?file=/src/index.js

Upvotes: 1

Lokendra Soni
Lokendra Soni

Reputation: 487

What you can do is, parse all the tr elements then loop through them to get the first and the second children (which are td elements) then the content of the first children would be the name value and for the elements, you can split the content of second children first with a / then with a ,. Check the below example snippet for more details

const trs = document.querySelectorAll("tr");

const items = Array.from(trs).map(tr => {
  const firstTd = tr.children[0].innerText;
  const secondTd = tr.children[1].innerText;
  
  const elements = secondTd.split(" / ").map(t => t.split(", "));
  
  return {
    name:firstTd,
    elements
  };
});

console.log(items)
<table>
  <tr>
    <td>Acid Rain</td>
    <td>
      rain, smoke / rain, smog / rain, sickness / cloud, smoke / cloud, smog
      / cloud, sickness / rain, city
    </td>
  </tr>
</table>

Upvotes: 2

trincot
trincot

Reputation: 350310

You can parse the HTML with DOMParser and then map each table row as follows:

const html = `<table border="1" cellspacing="1" cellpadding="1" style="width:468px"><tbody><tr><td> <b>Resulting Element</b></td><td> <b>Ingredient Combination(s)</b></td></tr><tr><td> Acid Rain</td><td> rain, smoke / rain, smog / rain, sickness / cloud, smoke / cloud, smog / cloud, sickness / rain, city</td></tr><tr><td> Air</td><td> Available from start.</td></tr><tr><td> Airplane</td><td> metal, bird / steel, bird / bird, machine / bird, steam engine / bird, train / bird, car / bird, boat / bird, steamboat / bird, sailboat / metal, owl / steel, owl / steam engine, owl / metal, vulture / steel, vulture / metal, duck / steel, duck / metal, seagull / steel, seagull / metal, bat / steel, bat / metal, eagle / steel, eagle / steel, pigeon / metal, pigeon / metal, hummingbird / steel, hummingbird / metal, crow / steel, crow / owl, machine / vulture, machine / duck, machine / seagull, machine / bat, machine / eagle, machine / pigeon, machine / hummingbird, machine / crow, machine / pilot, container</td></tr><tr><td> Alarm Clock</td><td> clock, sound / clock, dawn / clock, bell / sound, watch / watch, dawn / watch, bell</td></tr><tr><td> Alchemist</td><td> human, gold / gold, philosophy</td></tr><tr><td> Alcohol</td><td> time, juice / wheat, fruit / wheat, juice / fruit, sun</td></tr><tr><td> Algae</td><td> water, plant / grass, pond / grass, lake / water, grass</td></tr><tr><td> Alien</td><td> life, space / life, galaxy / life, galaxy cluster / life, solar system / life, Mars / life, Venus / life, Mercury / life, Jupiter / life, Saturn</td></tr><tr><td> Allergy</td><td> dust, human / human, pollen</td></tr></tbody></table>`;

const {body} = new DOMParser().parseFromString(html, "text/html");

const result = Array.from(body.children[0].rows, ({cells: [a, b]}) => ({
    name: a.textContent.trim(),
    elements: b.textContent.trim().split(" / ").map(pair => pair.split(", "))
}));
result.shift(); // Ignore first (header) row
console.log(result);

Upvotes: 1

Damien
Damien

Reputation: 633

if it's just a one time thing you could use https://www.convertjson.com/html-table-to-json.htm to generate json based on your table to make it easier to manipulate

Upvotes: 1

Related Questions