0

I have an array of objects.

[
  { _id: { year: 2020, month: 1 } },
  { _id: { year: 2019, month: 1 } },
  { _id: { year: 2019, month: 2 } },
  { _id: { year: 2019, month: 4 } },
  { _id: { year: 2019, month: 5 } },
  { _id: { year: 2019, month: 8 } },
  { _id: { year: 2019, month: 9 } },
  { _id: { year: 2019, month: 11 } }
]

I want to remove the duplicate year properties from the objects and push different month data in one array object.

I want to get below output:

[
  {
    "_id": {
      "year": 2020,
      "month": [1]
    }
  },
  {
    "_id": {
      "year": 2019,
      "month": [1, 2, 4, 5, 8, 9, 11]
    }
  }
]

I have tried but cannot get the expected output:

let arr = [
  { _id: { year: 2020, month: 1 } },
  { _id: { year: 2019, month: 1 } },
  { _id: { year: 2019, month: 2 } },
  { _id: { year: 2019, month: 4 } },
  { _id: { year: 2019, month: 5 } },
  { _id: { year: 2019, month: 8 } },
  { _id: { year: 2019, month: 9 } },
  { _id: { year: 2019, month: 11 } }
];

let newArr= []; 
    arr.forEach(function (item) { 
        let isMatch = newArr.filter(function (elem) {
            return elem._id.year === item._id.year 
        })
        if (isMatch.length == 0) {
            newArr.push(item)
        }
        else {
            newArr.find(x => x._id.year === item._id.year)._id.month.push(...item._id.month);
        }
    })
    console.log(newArr);

3 Answers 3

1

You can try using Array.reduce:

let input = [
  { _id: { year: 2020, month: 1 } },
  { _id: { year: 2019, month: 1 } },
  { _id: { year: 2019, month: 2 } },
  { _id: { year: 2019, month: 4 } },
  { _id: { year: 2019, month: 5 } },
  { _id: { year: 2019, month: 8 } },
  { _id: { year: 2019, month: 9 } },
  { _id: { year: 2019, month: 11 } }
];

let result = input.reduce((state, current) => {
   let prev = state.find(x => x._id.year === current._id.year);
   if(prev){
      prev._id.months.push(current._id.month);
   }
   else{
      state.push({_id: { year: current._id.year, months: [ current._id.month ] } });
   }
   return state;
},[]);

console.log(result);

Sign up to request clarification or add additional context in comments.

Comments

0

First make an object indexed by year, whose values are the months found for that year so far, and push to an array for the year (creating if necessary) on every iteration. Afterwards, transform the object of arrays into your output structure:

const input = [
  { _id: { year: 2020, month: 1 } },
  { _id: { year: 2019, month: 1 } },
  { _id: { year: 2019, month: 2 } },
  { _id: { year: 2019, month: 4 } },
  { _id: { year: 2019, month: 5 } },
  { _id: { year: 2019, month: 8 } },
  { _id: { year: 2019, month: 9 } },
  { _id: { year: 2019, month: 11 } }
];

const monthsByYear = {};
for (const { _id: { year, month } } of input) {
  if (!monthsByYear[year]) {
    monthsByYear[year] = [];
  }
  monthsByYear[year].push(month);
}
const output = Object.entries(monthsByYear).map(
  ([year, month]) => ({ _id: { year, month } })
);
console.log(output);

Comments

0

YOu can use reduce and findIndex and check if the accumulator array contains that year, then just push the month

let data = [{
    _id: {
      year: 2020,
      month: 1
    }
  },
  {
    _id: {
      year: 2019,
      month: 1
    }
  },
  {
    _id: {
      year: 2019,
      month: 2
    }
  },
  {
    _id: {
      year: 2019,
      month: 4
    }
  },
  {
    _id: {
      year: 2019,
      month: 5
    }
  },
  {
    _id: {
      year: 2019,
      month: 8
    }
  },
  {
    _id: {
      year: 2019,
      month: 9
    }
  },
  {
    _id: {
      year: 2019,
      month: 11
    }
  }
]

let newData = data.reduce((acc, curr) => {
  let isYrPresent = acc.findIndex((item) => {
    return item._id.year === curr._id.year;
  });

  if (isYrPresent === -1) {
    acc.push({
      _id: {
        year: curr._id.year,
        month: [curr._id.month]
      }
    })
  } else {
    acc[isYrPresent]._id.month.push(curr._id.month)
  }


  return acc;
}, []);

console.log(newData)

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.