Home > Net >  Group array Elements in a sequence JavaScript
Group array Elements in a sequence JavaScript

Time:08-06

I am trying to group weekdays together based on the property value in an array. I have used lodash to obtain a solution. My code looks like this,

const array = [{
    weekDay: 'Monday',
    hoursInfo: '11:00am-8:00pm',
  },
  {
    weekDay: 'Tuesday',
    hoursInfo: '11:00am-8:00pm',
  },
  {
    weekDay: 'Wednesday',
    hoursInfo: '9:00am-11:00am',
  },
  {
    weekDay: 'Thursday',
    hoursInfo: '11:00am-8:00pm',
  },
  {
    weekDay: 'Friday',
    hoursInfo: '11:00am-9:00pm',
  },
  {
    weekDay: 'Saturday',
    hoursInfo: '11:00am-9:00pm',
  },
  {
    weekDay: 'Sunday',
    hoursInfo: 'Closed',
  },
];
const result = _.chain(array).groupBy("hoursInfo").value();
document.getElementById("result").innerHTML = JSON.stringify(result);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
<div id="result"></div>

I am able to group the list of weekdays which has the same timings together, but my requirement is to group them in a sequence. My expected output is something like this,

Monday-Tuesday: 11:00am-8:00pm
Wedesday: 9:00am-11:00am
Thursday: 11:00am-8:00pm
Friday-Saturday: 11:00am-9:00pm
Sunday: Closed

Please help me with a better approach

CodePudding user response:

Reduce will work

const newArr = array.reduce((acc, item) => {
    if (acc.length && acc[acc.length - 1].hoursInfo === item.hoursInfo) {
      acc[acc.length - 1].weekDay  = `- ${item.weekDay}`;
    } else acc.push(item);
    return acc;
  }, [])
  .map(item => `${item.weekDay}: ${item.hoursInfo}`);

console.log(newArr)
<script>
  const array = [
    { weekDay: 'Monday',   hoursInfo: '11:00am-8:00pm' },
    { weekDay: 'Tuesday',  hoursInfo: '11:00am-8:00pm' },
    { weekDay: 'Wednesday',hoursInfo: '9:00am-11:00am' },
    { weekDay: 'Thursday', hoursInfo: '11:00am-8:00pm' },
    { weekDay: 'Friday',   hoursInfo: '11:00am-9:00pm' },
    { weekDay: 'Saturday', hoursInfo: '11:00am-9:00pm' },
    { weekDay: 'Sunday',   hoursInfo: 'Closed'}
  ];
</script>

CodePudding user response:

This solution should work, let me know if you need explanations :)

Edit: for some reasons i can't comment on mplungjan's answer but his solution won't work if there are more than two consecutives days with the same hoursInfo. Try to replace wednesday's hours by "11:00am-8:00pm" and you will get : 'Monday- Tuesday- Wednesday- Thursday: 11:00am-8:00pm'

const array = [{weekDay:"Monday",hoursInfo:"11:00am-8:00pm"},{weekDay:"Tuesday",hoursInfo:"11:00am-8:00pm"},{weekDay:"Wednesday",hoursInfo:"9:00am-11:00am"},{weekDay:"Thursday",hoursInfo:"11:00am-8:00pm"},{weekDay:"Friday",hoursInfo:"11:00am-9:00pm"},{weekDay:"Saturday",hoursInfo:"11:00am-9:00pm"},{weekDay:"Sunday",hoursInfo:"Closed"}];

const getHours = (array) => {

    let results = [];

    array.forEach((element, index) => {
        if(index === 0) return results.push([element.weekDay, element.hoursInfo]);

        if(element.hoursInfo === results[results.length - 1][1]) {
            const current = results[results.length - 1][0];
            results[results.length - 1][0] = `${current.split('-')[0]}-${element.weekDay}`;
        }
        else {
            results.push([element.weekDay, element.hoursInfo]);
        }
    })

    return results.map(element => `${element[0]}: ${element[1]}`).join('\n');
}


console.log(getHours(array));

CodePudding user response:

I don't think there is any magic function that will do that. You have to implement such algorithm by yourself. You can do this in two steps:

  1. Get day entry and check if it has the same hours as previous one
  2. if so, then add this to the group, if not the create a new group

const group = (data) => {
  const groups = [];

  data.forEach((entry) => {
    if (groups.length === 0) {
      // initial group
      groups.push({
        days: [entry.weekDay],
        hours: entry.hoursInfo,
      });
    } else if (groups[groups.length - 1].hours === entry.hoursInfo) {
      // the same hours
      groups[groups.length - 1].days.push(entry.weekDay);
    } else {
      // create a new group
      groups.push({
        days: [entry.weekDay],
        hours: entry.hoursInfo,
      });
    }
  });

  return groups;
};

const formatDays = (groups) => {
  return groups.map((group) => ({
    days: group.days.length > 1 ?
      `${group.days[0]}-${group.days[group.days.length - 1]}` :
      group.days[0],
    hours: group.hours,
  }));
};

const groupsData = group(array);
const formattedGroups = formatDays(groupsData);
console.log(formattedGroups);
<script>
  const array = [{
      weekDay: 'Monday',
      hoursInfo: '11:00am-8:00pm',
    },
    {
      weekDay: 'Tuesday',
      hoursInfo: '11:00am-8:00pm',
    },
    {
      weekDay: 'Wednesday',
      hoursInfo: '9:00am-11:00am',
    },
    {
      weekDay: 'Thursday',
      hoursInfo: '11:00am-8:00pm',
    },
    {
      weekDay: 'Friday',
      hoursInfo: '11:00am-9:00pm',
    },
    {
      weekDay: 'Saturday',
      hoursInfo: '11:00am-9:00pm',
    },
    {
      weekDay: 'Sunday',
      hoursInfo: 'Closed',
    },
  ];
</script>

  • Related