Reputation: 11
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
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
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
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
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