重构 JSON 对象数组
Posted
技术标签:
【中文标题】重构 JSON 对象数组【英文标题】:Restructuring Array of JSON objects 【发布时间】:2020-09-12 16:10:00 【问题描述】:我有一个 JSON 对象数组。但是,有些数据是重复的。有没有办法重组数组以排除重复值?我必须使用地图功能吗?还是 for 循环?
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'
]
是否可以像这样重构数据?
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']
]
如果您有任何指导或方向,将不胜感激! 谢谢!
【问题讨论】:
做一些研究以从数组生成一个 "groupBy" 对象 您真的要分别对Time
和Date
进行分组和去重吗?根据我的经验,在大多数用例中,时间仅在某一天才有意义。
看起来它实际上会破坏数据,不是吗?没有日期上下文的去重复时间会被破坏吗?
感谢大家的回复。我很想显示所有时间和日期,无论它们是否对应。只要他们不重复。再次感谢您的帮助。
【参考方案1】:
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)
【讨论】:
【参考方案2】:编辑:修复通过使用 DateTime 字符串的 Set() 过滤重复的 DateTimes 以保持相应的顺序
注意:可选链接 ?.
需要 Chrome 80+ 和 Safari 13+。如果需要兼容性,请对未定义使用三元检查。
使用对象映射来跟踪重复的 id,如果找到,则连接到时间数组。
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)
)
【讨论】:
预期结果需要对Time
和 Date
数组进行重复数据删除,因此您的答案(尚未)100% 准确。【参考方案3】:
我做到了:
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;
【讨论】:
【参考方案4】:根据MDN,Map
比使用Object
更合适。集合用于确保对所有值进行重复数据删除。
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)
【讨论】:
以上是关于重构 JSON 对象数组的主要内容,如果未能解决你的问题,请参考以下文章
原生JavaScript对象数组去重,重构为对象{pro1:[hash], pro02: [hash]}