0

I am working with some data collected from a Json file. With a react fetch function I have created an object called "category_evolution". I am trying to use a map function to create a table with that object.

category_evolution =

[
    {
        "name": "01/02/2023",
        "data": [
            {
                "id": 30,
                "category": "Criptomoedas",
                "category_total_brl": "12000.00",
                "category_total_usd": "2400.00",
                "date": "01/02/2023"
            },
            {
                "id": 28,
                "category": "REITs",
                "category_total_brl": "16000.00",
                "category_total_usd": "3200.00",
                "date": "01/02/2023"
            },
            {
                "id": 26,
                "category": "Stocks",
                "category_total_brl": "20100.00",
                "category_total_usd": "4020.00",
                "date": "01/02/2023"
            }
        ]
    },
    {
        "name": "01/01/2023",
        "data": [
            {
                "id": 29,
                "category": "Criptomoedas",
                "category_total_brl": "10000.00",
                "category_total_usd": "2000.00",
                "date": "01/01/2023"
            },
            {
                "id": 27,
                "category": "REITs",
                "category_total_brl": "15000.00",
                "category_total_usd": "3000.00",
                "date": "01/01/2023"
            },
            {
                "id": 25,
                "category": "Stocks",
                "category_total_brl": "20000.00",
                "category_total_usd": "4000.00",
                "date": "01/01/2023"
            }
        ]
    }
]

Here is my table code:


<table className="table">
  <thead>
    <tr>
      <th scope="col">Categoria</th>
      {category_evolution.map(({ name }) => (
        <th scope="col" key={name}>{name}</th>
      ))}
    </tr>
  </thead>
  <tbody>
    {category_evolution.map(({ data }) =>
        data.map(({ id, category, category_total_brl }) => (
          <tr key={id}>
            <td>{category}</td>
            <td>{category_total_brl}</td>
          </tr>
        ))
      )}
  </tbody>
</table>

The output of this code is a table like that

Categoria            01/02/2023      01/01/2023

Criptomoedas         12000.00
REITs                16000.00
Stocks               20100.00

Criptomoedas         10000.00
REITs                15000.00
Stocks               20000.00

But I would like to achieve an output like this:

Categoria            01/02/2023      01/01/2023

Criptomoedas         12000.00        10000.00
REITs                16000.00        15000.00
Stocks               20100.00        20000.00

I appreciate any help you can provide.

2 Answers 2

1

One way to do it is to combine all the data into a single array and then to map that array into an object where keys are the categories and the values are combined data for each "date":

const combinedData = category_evolution.reduce((acc, cur) => {
  return [...acc, ...cur.data];
}, []);

const categoryMap = combinedData.reduce((acc, cur) => {
  if(!acc[cur.category]) {
    acc[cur.category] = [cur];
    return acc;
  }
  acc[cur.category].push(cur);
  return acc;
}, {});

And then the JSX:

<table className="table">
  <thead>
    <tr>
      <th scope="col">Categoria</th>
      {category_evolution.map(({ name }) => (
        <th scope="col" key={name}>{name}</th>
      ))}
    </tr>
  </thead>
  <tbody>
    {Object.keys(categoryMap).map(category => {
      return (
        <tr key={category}>
          <th>{category}</th>
          <td>{categoryMap[category][0].category_total_brl}</td>
          <td>{categoryMap[category][1].category_total_brl}</td>
        </tr>
      )
    })}
  </tbody>
</table>
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, that worked fine for the example, but would be possible to make it work with a flexible number of data, for example, 12 dates? But also work for 2 dates?
Added an answer with a nested map that will be used to iterate over the values for each category, that will allow flexibility in case there are more or less values for each category in the future.
@DiogoWernik Thanks. I figured you'd improve on that answer.
1

Combined data provided from @o4ohel

const combinedData = category_evolution.reduce((acc, cur) => {
  return [...acc, ...cur.data];
}, []);

const categoryMap = combinedData.reduce((acc, cur) => {
  if(!acc[cur.category]) {
    acc[cur.category] = [cur];
    return acc;
  }
  acc[cur.category].push(cur);
  return acc;
}, {});

Here's an updated version of the code provided by @o4ohel that can be improved for readability and maintainability:


<table className="table">
    <thead>
        <tr>
        <th scope="col">Categoria</th>
        {category_evolution.map(({ name }) => (
            <th scope="col" key={name}>{name}</th>
        ))}
        </tr>
    </thead>
    <tbody>
    {Object.entries(categoryMap).map(([category, values]) => (
        <tr key={category}>
            <th>{category}</th>
            {values.map(({ id, category_total_brl }) => (
            <td key={id}>{category_total_brl}</td>
            ))}
        </tr>
        ))}
    </tbody>
</table>

A nested map is used to iterate over the values for each category, which allows for greater flexibility in case there are more or less values for each category in the future.

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.