captainanders29
captainanders29

Reputation: 11

Restructuring Array of JSON objects

I have an array of JSON objects. However, some of the data is repeated. Is there a way to restructure the array to exclude repeated values? Do I have to use the Map function? or a for loop?

userData = [{id:'101', Time:'3:00pm', Date:'5/25/20'},
            {id:'101', Time:'5:00pm', Date:'5/25/20'},
            {id:'101', Time:'5:00pm', Date:'6/25/20'},
            {id:'105', Time:'1:00pm', Date:'3/25/20'},
            {id:'105', Time:'5:00pm', Date:'5/25/20'}
           ]

Is it possible to restructure the data like so?

userData = [ {id:'101', Time:['3:00pm','5:00pm'], Date:['5/25/20', '6/25/20']},
             {id:'105', Time:['1:00pm','5:00pm'], Date:['3/25/20','5/25/20']}
           ]

If you have any guidance or direction, it would be greatly appreciated! Thank you!

Upvotes: 1

Views: 223

Answers (4)

user120242
user120242

Reputation: 15268

EDIT: fixed to filter duplicate DateTimes maintaining corresponding order by using a Set() of DateTime strings

Note: optional chaining ?. requires Chrome 80+ and Safari 13+. Use ternary check for undefined if you need compatibility.

Use object map to track duplicate id, concat to Time array if found.

userData = [{id:'101', Time:'3:00pm', Date:'5/25/20'},
            {id:'101', Time:'5:00pm', Date:'5/25/20'},
            {id:'101', Time:'5:00pm', Date:'6/25/20'},
            {id:'105', Time:'1:00pm', Date:'3/25/20'},
            {id:'105', Time:'5:00pm', Date:'5/25/20'}
           ]
console.log(
Object.values(
userData.reduce((acc,{Time, id, Date})=>
  // [id] exists and does not contain DateTime
  acc[id]?.TD?.has(`${Date}_${Time}`)!== true ? 
  Object.assign(acc, {[id]:{
      id, 
      TD: (acc[id]?.TD||new Set()).add(`${Date}_${Time}`),
      Time: (acc[id]?.Time||[]).concat(Time),
      Date: (acc[id]?.Date||[]).concat(Date)
   }})
   : acc,{})
)
// get rid of TD Set, used only to prevent dupes
.map(({TD, ...o})=>o)
)

Upvotes: 1

Jager567
Jager567

Reputation: 627

According to MDN, Map is a better fit than using an Object. Sets are used to ensure all values are deduplicated.

userData = [{id:'101', Time:'3:00pm', Date:'5/25/20'},
            {id:'101', Time:'5:00pm', Date:'5/25/20'},
            {id:'101', Time:'5:00pm', Date:'6/25/20'},
            {id:'105', Time:'1:00pm', Date:'3/25/20'},
            {id:'105', Time:'5:00pm', Date:'5/25/20'},
           ];

const structure = new Map();

userData.forEach(el => {
  const {t, d} = structure.get(el.id) || {t: new Set(), d: new Set()};
  structure.set(el.id, { t: t.add(el.Time), d: d.add(el.Date) });
});

const restructured = 
  [...structure].map(el => ( {id: el[0], Time: [...el[1].t], Date: [...el[1].d]} ))

console.log(restructured)

Upvotes: 0

Rômulo Rocha
Rômulo Rocha

Reputation: 61

let userData = [{id:'101', Time:'3:00pm', Date:'5/25/20'},
        {id:'101', Time:'5:00pm', Date:'5/25/20'},
        {id:'101', Time:'5:00pm', Date:'6/25/20'},
        {id:'105', Time:'1:00pm', Date:'3/25/20'},
        {id:'105', Time:'5:00pm', Date:'5/25/20'}
       ]

let formattedUserData = {}

userData.forEach(user=>{
  if(!formattedUserData[user.id]) formattedUserData[user.id]= {
    id: user.id,
    Time: [],
    Date: [],
  }
  formattedUserData[user.id].Time.push(user.Time)
  formattedUserData[user.id].Date.push(user.Date)
})

const finalResponse = Object.entries(formattedUserData).map((e) => ( { ...e[1] } ));
console.log("finalResponse",finalResponse)

Upvotes: 1

Mister Jojo
Mister Jojo

Reputation: 22320

I done that:

const userData = 
    [ { id: '101', Time: '3:00pm', Date: '5/25/20'} 
    , { id: '101', Time: '5:00pm', Date: '5/25/20'} 
    , { id: '101', Time: '5:00pm', Date: '6/25/20'} 
    , { id: '105', Time: '1:00pm', Date: '3/25/20'} 
    , { id: '105', Time: '5:00pm', Date: '5/25/20'} 
    ] 
      
const result = userData.reduce((a,{id,Time,Date})=>{
  let el = a.find(ud=>ud.id===id)
  if (!el) { el = {id, Time:[], Date:[]};  a.push(el) }
  if (!el.Time.includes(Time)) el.Time.push(Time)
  if (!el.Date.includes(Date)) el.Date.push(Date)
  return a
  }, [])

console.log( JSON.stringify(result,0,2) )
.as-console-wrapper { max-height: 100% !important; }

Upvotes: 0

Related Questions