【发布时间】:2016-10-14 11:13:56
【问题描述】:
假设我有以下数据
var obj = {
test: 'somedata',
scores: [
{
"points":99,
"id":"x12"
},
{
"points":21,
"id":"x13"
}
],
sites: [
{
"exercises":21,
"sid":"s12"
},
{
"exercises":23,
"sid":"s11"
}
],
history: {
key: 'value',
commits: [
{
id: 1,
value: 'thank you'
}
]
}
}
请注意,scores 和 sites 包含的数组具有基于 scores 中的 id 和 sites 中的 sid 的唯一元素。我想要一个具有以下魔力的函数:
//will **update** obj.test to 'newdata' and return {test:'newdata'}
magicUpdate(obj, {test:'newdata'})
//will **insert** obj.newkey with with value 'value' and return {newkey: 'value'}
magicUpdate(obj, {newkey: 'value'})
//will do nothing and return {}
magicUpdate(obj, {scores: []})
//will **update** scores[0] and return {scores:[{points:3, id: "x12"}]}, as id "x12" is already in the array at index 0
magicUpdate(obj, {scores:[{points:3, id: "x12"}])
//will **insert** {points:3, id: "x14"} into obj.scores and return {scores:[{points:3, id: "x14"}]}
magicUpdate(obj, {scores:[{points:3, id: "x14"}]})
//will **update** sites[0] and return {sites:[{exercises:22, sid: "s12"}]}, as id "s12" is already in the array at index 0
magicUpdate(obj, {sites:[{exercises:22, sid: "s12"}])
//will **insert** {exercises:10, sid: "s14"} into obj.sites and return {sites:[{exercises:10, sid: "s14"}]}
magicUpdate(obj, {sites:[{exercises:10, sid: "s14"}]})
//and also be recursive ...
//will **update** obj.history.commits[0]
magicUpdate(obj, {'history.commits': [{id:1, value: 'changed'}]});
我见过.update 进行递归,但前提是有人通过path 应该自动确定。然后是.merge,它在内部使用_.baseMerge,虽然我不理解函数的签名,但它确实接近我需要的东西。
_.merge(
{scores:[{id: 12, points:10}, {id: 13, points:10}]},
{scores:[{id: 14, points:10}, {id: 15, points:10}]}
)
// returns {scores:[{id: 14, points:10}, {id: 15, points:10}]} not the fully merged array
谁能给我指出一个好的方向或者用 lodash 实现了类似的事情?
【问题讨论】:
-
到目前为止你尝试了什么?
-
我尝试编写自己的函数,但当我注意到我还需要递归时,结果并不好。然后我找到了上面的 lodash 函数,想到之前可能有人遇到过同样的问题。
-
我注意到合并对对象和嵌套对象非常有效。也许我只是尝试将我的数据结构从
scores : [{id: s1, points:2},...]转换为scores:{s1:{points:2},...}
标签: javascript arrays object insert lodash