0

I'm quite new to both react and JavaScript and would really appreciate some advice on this. I want to iterate through a nested array like the one below by using the map() method:

const demos = [
    {
      id : '1',
      name: 'name1',
      dates:  ['jan', 'feb', 'apr']
    }, 
    {
      id : '2',
      name: 'name2',
      dates: ['feb', 'may']
    }
];

I want to first map through the first object with the first date and then the second date and so on, before going to the next object and then sort it based on date to ideally achieve the following output:

name1: jan 
name1: feb
name2: feb
name1: apr
name2: may

The only not quite working solution I've come up with this far is:

import * as React from 'react';

const demos = [
    
        {id : '1',
        name: 'name1',
        dates:  ['jan', 'feb', 'apr']
        }, 
        {id : '2',
        name: 'name2',
        dates: ['feb', 'may']
        }
                
];

const counts = ['0','1','2'];

export default function Test() {
        
    return (
      <div>
      {
        counts.map(count => (
          demos.map(demo =>(
            <div key={demo.id}>
              <div>{demo.name}: {demo.dates[count]}</div>
            </div>
           ))
         ))
       }
       </div>
    );
}

which gives me the following output:

name1: jan
name2: feb
name1: feb
name2: may
name1: apr
name2:

using the const counts isn't really working and doesn't feel like the proper way to begin with. How can I do this in a good way and then sort it by date ?

4 Answers 4

1

One is able to provide a workable code using stack-snippets like below:

const demos = [
    
        {id : '1',
        name: 'name1',
        dates:  ['jan', 'feb', 'apr']
        }, 
        {id : '2',
        name: 'name2',
        dates: ['feb', 'may']
        }
                
];

// const counts = ['0','1','2'];

function Test() {
  const sortHelper = Object.fromEntries(("jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec")
    .split(", ").map((m, idx) => ([m, idx])));

  const transformArr = arr => (
    [...arr].map(({name, dates}) => (
      dates.map(month => ({ name, month }))
    ))
    .flat()
    .sort((a, b) => (sortHelper[a.month] - sortHelper[b.month]))
  );
  return (
    <div>
    {
      transformArr(demos).map(({name, month}) => (
        <div>{name}: {month}</div>
      ))
    }
    </div>
  );
}

ReactDOM.render(
  <div>
    DEMO
    <Test />
  </div>,
  document.getElementById("rd")
);
<div id="rd"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>

Explanation

  • In order to sort using "jan, feb, mar... dec", a sortHelper object is created
  • Iterate over the array using .map and de-structure name, dates
  • Now, iterate over the dates to create an object with two props name, month
  • This object closely resembles the intended target
  • Use .flat() to remove nested arrays
  • Use .sort() in conjunction with sortHelper to provide the necessary order
Sign up to request clarification or add additional context in comments.

1 Comment

This works brilliantly thanks! In my file I've changed the months to date strings e.g '2022-10-10' and can thus avoid using the const sortHelper and instead use new Date()when sorting in transformArr. Thanks again!
1

Sorted

const App = () => {
  const demos = [
    { id: "1", name: "name1", dates: ["jan", "feb", "apr"] },
    { id: "2", name: "name2", dates: ["feb", "may"] }
  ];

  const monthIdx = {
    jan: 1,
    feb: 2,
    mar: 3,
    apr: 4,
    may: 5,
    jun: 6,
    jul: 7,
    aug: 8,
    sep: 9,
    oct: 10,
    nov: 11,
    dec: 12
  };

  const sortedDemo = demos
    .map((demo) => {
      return demo.dates.map((date) => ({ [demo.name]: date }));
    })
    .flat()
    .sort((a, b) => {
      const monthA = Object.values(a)[0];
      const monthB = Object.values(b)[0];
      return monthIdx[monthA] - monthIdx[monthB];
    });

  return sortedDemo.map((demo) => {
    const [key] = Object.entries(demo);
    const [name, date] = key;
    return (
      <div>
        {name} - {date}
      </div>
    );
  });
};

Without sort

const demos = [
  { id: "1", name: "name1", dates: ["jan", "feb", "apr"] },
  { id: "2", name: "name2", dates: ["feb", "may"] }
];

return demos.map((demo) => {
  return demo.dates.map((date) => (
    <div>
      {demo.name} - {date}
    </div>
  ));
});

1 Comment

Thanks so much! This works! Any thoughts on how I can sort the outcome by date before mapping it out? Thanks!
0

Implement the following code into your

{demo.name}: {`demo.dates.map((e) => {e} )`} It should works.

2 Comments

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
Thanks for this! I couldn't get the above to quite work but I made the following slight adjustment and it worked! demos.map(demo =>( <div key={demo.id}> { demo.dates.map((e)=> <div>{demo.name}:{e}</div> ) } </div> ))
0

Perhaps using a bucket sort would help:

const demos = [
  { id : '1', name: 'name1', dates:  ['jan', 'feb', 'apr'] },
  { id : '2', name: 'name2', dates: ['feb', 'may'] }
];

const month_indexes = {
  'jan': 0, 'feb': 1, 'mar': 2, 'apr': 3, 'may': 4, 'jun': 5,
  'jul': 6, 'aug': 7, 'oct': 8, 'sep': 9, 'nov': 10, 'dec': 11,
};

const get_sorted_entries = (items) =>
  items
    .reduce((acc, item) => {
      item.dates.forEach((date) => {
        // for some reason the below line won't run as acc[month_indexes[date]] ||= [];
        acc[month_indexes[date]] = acc[month_indexes[date]] || [];
        acc[month_indexes[date]].push([item, date]);
      });
      return acc;
    }, [])
    .flat();

const App = () => {
  return (
    <React.Fragment>
      {
        get_sorted_entries(demos).map(([item, month]) => (
          <div key={item.id + '-' + month}>{item.name}: {month}</div>
        ))
      }
    </React.Fragment>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>

Here an array is created of arrays of items, with the top level array being indexed by month. Using flat() unindexes by month but retains the order.

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.