skip to Main Content

I’m trying to use reduce to take an array of objects and return an object in below expected format. Able to use it to create object based on validFrom but not able to visulize next steps. Tried to use map as well but didn’t helped much. Help would be really appreciated! Can share stackblitz if helps.

Tried this to simplify but got stuck in next step. First comment

inputArray:
[
  {
    "day": "Wednesday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Tuesday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Sunday",
    "closeTime": "1630",
    "openTime": "0845",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Thursday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Friday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Saturday",
    "closeTime": "1630",
    "openTime": "0845",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Monday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  }
]

Code used:

let clubbedArray = normalData.reduce((acc, temp) => { let { validFrom, day } = temp; return {...acc, [validFrom]: [...(acc[validFrom] || []), day]}; }, {});

Expected Output:

[
  {
    "day": [
      "Friday",
      "Wednesday",
      "Monday",
      "Tuesday",
      "Thursday"
    ],
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": [
      "Saturday",
      "Sunday"
    ],
    "closeTime": "1630",
    "openTime": "0845",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  }
]

2

Answers


  1. You can use Array.prototype.reduce function to change the shape on an array as you want, Here is the code which allow you to change the shape of your data

    let data = [
      {
        "day": "Wednesday",
        "closeTime": "2000",
        "openTime": "0800",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      },
      {
        "day": "Tuesday",
        "closeTime": "2000",
        "openTime": "0800",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      },
      {
        "day": "Sunday",
        "closeTime": "1630",
        "openTime": "0845",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      },
      {
        "day": "Thursday",
        "closeTime": "2000",
        "openTime": "0800",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      },
      {
        "day": "Friday",
        "closeTime": "2000",
        "openTime": "0800",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      },
      {
        "day": "Saturday",
        "closeTime": "1630",
        "openTime": "0845",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      },
      {
        "day": "Monday",
        "closeTime": "2000",
        "openTime": "0800",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      }
    ];
    
    const result = data.reduce((accumulator, current) => {
       /*
           Check if there is an object on the result array with the corresponding closeTime if that is the case we return it index
       */
       let exists = accumulator.findIndex(item => {
           return item.closeTime == current.closeTime;
       })
       
       // if there is not item with that closeTime the result of the findIndex will be `-1` if so we add an object with the corresponding closeTime with all property of the `current` item of the reduce loop
       if(exists === -1) {
           accumulator = accumulator.concat({
              day: [current.day],
              closeTime: current.closeTime,
              openTime: current.openTime,
              validFrom: current.validFrom,
              validTo: current.validTo,
           })
       } else {
           accumulator[exists].day.push(current.day);
       }
       return accumulator;
    }, []);
    
    console.log(result);
    Login or Signup to reply.
  2. Pseudocode:

    1. Use the reduce() method to iterate over the array.
    2. Check if the current object matches any of the existing objects in the accumulator array (acc). -- iterate
         2.1. If the properties match: 
             2.1.1. Add the current object's day property to the matching object's day array.
             2.1.1. else, we create a new object with the current object's properties and push it to the acc array.
    3. Return the accumulator array.
    

    Implementation:

    const normalData = [{
        "day": "Wednesday",
        "closeTime": "2000",
        "openTime": "0800",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      },
      {
        "day": "Tuesday",
        "closeTime": "2000",
        "openTime": "0800",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      },
      {
        "day": "Sunday",
        "closeTime": "1630",
        "openTime": "0845",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      },
      {
        "day": "Thursday",
        "closeTime": "2000",
        "openTime": "0800",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      },
      {
        "day": "Friday",
        "closeTime": "2000",
        "openTime": "0800",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      },
      {
        "day": "Saturday",
        "closeTime": "1630",
        "openTime": "0845",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      },
      {
        "day": "Monday",
        "closeTime": "2000",
        "openTime": "0800",
        "validFrom": "2001-09-19",
        "validTo": "2099-12-31"
      }
    ];
    
    const combinedData = normalData.reduce((acc, curr) => {
      let found = false;
      acc.forEach((item) => {
        if (
          item.closeTime === curr.closeTime &&
          item.openTime === curr.openTime &&
          item.validFrom === curr.validFrom &&
          item.validTo === curr.validTo
        ) {
          item.day.push(curr.day);
          found = true;
        }
      });
      if (!found) {
        acc.push({
          day: [curr.day],
          closeTime: curr.closeTime,
          openTime: curr.openTime,
          validFrom: curr.validFrom,
          validTo: curr.validTo,
        });
      }
      return acc;
    }, []);
    
    console.log(combinedData);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search