Combine Array of Objects with similar keys conditionally using JavaScript

javascript merge array of objects by key
merge two arrays with same keys javascript
merge duplicate objects in array javascript
javascript merge two arrays without duplicates
javascript merge objects
concat multiple arrays javascript
merge two arrays as key value pairs javascript
javascript merge two objects without duplicates

I have an array of objects like :

const data = [
    {
        day: 'monday',
        time: '10:00 AM',
        type: 'start',
        unit: 1
    },
    {
        day: 'monday',
        time: '11:30 AM',
        type: 'end',
        unit: 1
    },
    {
        day: 'tuesday',
        time: '01:00 PM',
        type: 'start',
        unit: 1
    },
    {
        day: 'tuesday',
        time: '06:00 PM',
        type: 'end',
        unit: 1
    },
    {
        day: 'wednesday',
        time: '10:00 AM',
        type: 'start',
        unit: 1
    },
    {
        day: 'wednesday',
        time: '06:00 PM',
        type: 'end',
        unit: 1
    }
];

I need to combine two objects with same 'day' key (for ex.day:'monday' )into one where if object contains type: 'start' then it will be 'start_time': '10:00 AM' in the new object and if 'type': 'end' then it will be 'end_time': 11:30 AM in the new object. sr_no starts with 1 and is incremented by 1. It(array of new objects) should look something like this:

 var newArray = [    
        {
            sr_no: 1,
            day: 'monday',
            start_time: '10:00 AM',
            end_time: '11:30 AM',
            unit: 1
        },
        {
            sr_no: 2,
            day: 'tuesday',
            start_time: '01:00 PM',
            end_time: '06:00 PM',
            unit: 1
        },
        {
            sr_no: 3,
            day: 'wednesday',
            start_time: '10:00 AM',
            end_time: '06:00 PM',
            unit: 1
        }
];

Any suggestions please?

You can use Array.prototype.reduce to aggregate the data by day and Object.keys with Array.prototype.map to format it to the desired output:

const data=[{day:'monday',time:'10:00 AM',type:'start',unit:1},{day:'monday',time:'11:30 AM',type:'end',unit:1},{day:'tuesday',time:'01:00 PM',type:'start',unit:1},{day:'tuesday',time:'06:00 PM',type:'end',unit:1},{day:'wednesday',time:'10:00 AM',type:'start',unit:1},{day:'wednesday',time:'06:00 PM',type:'end',unit:1}];


const grouped = data.reduce((all, {day, time, type, unit}) => {

  if (!all.hasOwnProperty(day)) all[day] = { day, unit };

  all[day][`${type}_time`] = time;

  return all;

}, {});

const result = Object.keys(grouped).map((a,i) => ({sr_no: i + 1, ...grouped[a]}));

console.log(result);

2 Ways to Merge Arrays in JavaScript, Here are 2 ways to combine your arrays and return a NEW array. Whereas if I look at Version B, it appears like I'm adding the trucks array to the cars array, and it doesn't seem I'll just write some conditional to make sure what I'm passing is an array and execute accordingly. Creating Objects with ES6 Dynamic Keys. Now we need to merge the two array of objects into a single array by using id property because id is the same in both array objects. Note: Both arrays should be the same length to get a correct answer. First way. Here we are the using map method and Object.assign method to merge the array of objects by using id.

You can use map to transform the data to what you need, though how your sr_no is determined is not entirely clear.

const data = [
    {
        day: 'monday',
        time: '10:00 AM',
        type: 'start',
        unit: 1
    },
    {
        day: 'monday',
        time: '11:30 AM',
        type: 'end',
        unit: 1
    },
    {
        day: 'tuesday',
        time: '01:00 PM',
        type: 'start',
        unit: 1
    },
    {
        day: 'tuesday',
        time: '06:00 PM',
        type: 'end',
        unit: 1
    },
    {
        day: 'wednesday',
        time: '10:00 AM',
        type: 'start',
        unit: 1
    },
    {
        day: 'wednesday',
        time: '06:00 PM',
        type: 'end',
        unit: 1
    }
];


const transform = input => input
  .map(dayData => dayData.day)
  .map(day => input.filter(dayData => dayData.day === day))
  .map(bothTimes => ({
    day: bothTimes[0].day,
    start_time: bothTimes.filter(dayData => dayData.type === 'start')[0].time,
    end_time: bothTimes.filter(dayData => dayData.type === 'end')[0].time,
    unit: bothTimes[0].unit
  }))
  
const result = transform(data)
console.dir(result)

How to merge properties of two JavaScript objects dynamically , It is mostly used in the variable array where there is more than 1 values are expected. It allows the privilege to obtain a list of parameters from an array. Javascript objects are key-value paired dictionaries. We can merge different objects into one using the spread (…) Example 2: Suppose the objects have the same keys. In  key1, key2 and key3 need to be merged into array1 for intersecting objects; id of array2 needs to be mapped to new_id in array1; If no intersecting object, then defaultOptions need to be applied to array1; So that the output should look like:

If your datas will always be sorted so one day is always next to the same, you can easily go with one good old for loop:

const newArray = [];

for (let i = 0, n = 1; i < data.length; i += 2, n++) {
  const sr_no = n;
  const day = data[i].day;
  const start_time = data[i].type === 'start' ? data[i].time : data[i + 1].time;
  const end_time = data[i].type === 'end' ? data[i].time : data[i + 1].time;
  const unit = data[i].unit;

  newArray.push({
    sr_no,
    day,
    start_time,
    end_time,
    unit
  });
}

If your datas are not sorted to use this kind of loop, then just sort it before using a good sort() callback.

Conditionally adding entries inside Array and object literals, Cover of book “JavaScript for impatient programmers”. Book, exercises Conditionally adding entries inside Array and object literals You can use the proposed spread operator for properties in the same manner. Again  I know that there is a way of doing this by going from result1 compare each object with the objects of result2, then compare their keys, and if did'n match, put the values in another object then push it in new array, but I wonder is there any more elegant way, like using lo-dash or underscore or something similar.

Calculates the correct sr_no according to your output.

const data = [
    {
        day: 'monday',
        time: '10:00 AM',
        type: 'start',
        unit: 1
    },
    {
        day: 'monday',
        time: '11:30 AM',
        type: 'end',
        unit: 1
    },
    {
        day: 'tuesday',
        time: '01:00 PM',
        type: 'start',
        unit: 1
    },
    {
        day: 'tuesday',
        time: '06:00 PM',
        type: 'end',
        unit: 1
    },
    {
        day: 'wednesday',
        time: '10:00 AM',
        type: 'start',
        unit: 1
    },
    {
        day: 'wednesday',
        time: '06:00 PM',
        type: 'end',
        unit: 1
    }
];

const update = (arr)=>{
   const x = {}
   
   const constructObj = (item,indx)=>{
       const original = x[item.day] || {};
       const key = item.type === 'start'? 'start_time':'end_time';
       original.sr_no = Object.keys(x).indexOf(item.day)+1;
       original[key] = item.time;
       original.unit = item.unit;
       return original;
   }
  
   arr.forEach((item,indx)=>{
       x[item.day] = constructObj(item,indx);
   })
  
   return x;
}

console.log(update(data));

Adding object properties conditionally with EcmaScript 6 (ES6), Adding a property to an object is quite easy in JavaScript. This still looks fine but what if we combine conditions and add them into multiple if blocks? The result of the value of person would be the same as in the script mentioned the person object to actually pass an object rather than key and a value. Note: The above solution is to just merge two arrays using ES6 spread operator. Edit on 07 January 2020 by @bh4r4th : As the context changed due to edits after my initial solution. I would like to update my solution to match current criteria. i.e., Merger array objects without creating duplicate objects and,

Combining JavaScript Arrays, We're going to cover different methods for combining/merging two JS arrays, and the pros/cons of each approach. OK, let's just append one array 's contents onto the other, using Array#push(..) : // `b` onto but you'll have the same conclusions as with push(. Strings are immutable objects in javascript. As you can see, using .reduce() is an easy way to generate a single value or object from an array. .filter() What if you have an array, but only want some of the elements in it?

Merge Object Properties with the Spread Operator, is for working with arrays and other iterable objects. operator while I tinker with Babel and React: merging multiple objects' properties into one object! The JavaScript. Wrap any objects you'd like merged into one with braces ( {} ): In the case of a key collision, the right-most (last) object's value wins out: The concat() method is used to join two or more arrays. This method does not change the existing arrays, but returns a new array, containing the values of the joined arrays.

Conditionally adding keys to JavaScript objects using spread , Today I needed to create a JavaScript object to pass to MongoDB, based on some request query parameters. Today I learned, thanks to this Stack Overflow  Spread syntax allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

Comments
  • What have you tried so far and what difficulties did you have with your attempts?
  • are they always ordered like this, if so you could just merge data[i] and data[i+1] then i+=2
  • Hi! Please take the tour (you get a badge!) and read through the help center, in particular How do I ask a good question? Your best bet here is to do your research, search for related topics on SO, and give it a go. If you get stuck and can't get unstuck after doing more research and searching, post a minimal reproducible example of your attempt and say specifically where you're stuck. People will be glad to help.
  • I tried using reduce to parse using current value and next value but it would not construct an object like i want data.reduce(function(prev, curr){ if(prev.day === curr.day) { output.day = prev.day; output.start_time = prev.time; output.end_time = curr.time; output.unit = prev.unit; } })