所以我和一位同事一起工作,他向我展示了如何解决一个特定的问题:如何将扁平物体变成嵌套物体。对象属性以这样的方式命名,即可以将它们切片到其命名的相关键中,然后嵌套。他的解决方案效果很好,但是当我自己编写代码时,我无法理解它是如何工作的。
我实际上是从一个excel工作表并从中创建json但是为了论证,我将删除excel部分并添加excel解析器出来的示例结构:
//Example data
var result = {
frame1.title: "heading",
frame1.division: "first",
frame1.data[0].month: "Jan",
frame1.data[0].value: "54",
}
function deepInsert (o, path, value) {
let next, cur = o
path.forEach((p,i) => {
next = cur[p]
if (i == path.length -1) {
cur[p] = value
} else {
if (!next) {
next = cur[p] = {}
}
cur = next
}
})
}
function processWorkbook () {
const result = json.map(item => {
var o = {foo: "bar"}
Object.keys(item).forEach(prop => {
deepInsert(o, prop.split('.'), item[prop])
console.log(JSON.stringify(o, 0, ' '));
})
return o
})
console.log(JSON.stringify(result, 0, ' '))
}
从我可以看出它看起来像是传递'o',这是一个空白对象,然后deepInsert函数中的循环将数据分配给param,而不是调用函数中的对象,因为每次通过循环,我的控制台日志显示更多被添加到对象。
我也不明白这一部分:next = cur[p] = {}
。出于某种原因,三重分配会在chrome repl中引发错误,但在该函数中却没有?我很困惑,任何帮助都会很棒!
答案 0 :(得分:1)
函数deepInsert
包含以下参数:
'foo.bar.x'
需要成为['foo','bar', 'x']
)并且这样做:
函数processWorkbook
只是迭代对象键以将参数发送到deepInsert
函数。这可以直接在deepInsert
上完成。
就是这样。问题是函数有未使用的变量和复杂的代码。一个更简单和记录的功能:
function unnestObject(obj = {}) {
let newObject = {}, //The object to return
current; // the object position holder
for (var key in obj) { // iterate on recived object keys
current = newObject // Makes the current object the new Object root
let path = key.split('.') // Split the current key
path.forEach((p, i) => { // iterate on the key paths
if ((path.length - 1) !== i) //if the path isn't the last one
current[p] = current[p] || {} // initialize a new object on that path (if a object was previously initialized, it is preserved)
else //if the path is the last one
current[p] = obj[key] // sets the value of the initial object key
current = current[p] // Updates the current to the next node
})
}
return newObject; //returns the new object
}
//Example data [DOESNT WORK WITH ARRAYS]
var data = {
"frame1.title": "heading",
"frame1.division": "first",
"frame1.data.month": "Jan",
"frame1.data.value": "54",
}
console.log(unnestObject(data))
// Prints
// {
// "frame1": {
// "title": "heading",
// "division": "first",
// "data": {
// "month": "Jan",
// "value": "54"
// }
// }
// }
注意:这两个函数都不支持数组,如果传递{"foo.bar[0].value": 42}
之类的内容,foo.bar
将是一个对象。您可以检测数组[]
键并使其初始化数组而不是迭代中的对象
关于next = cur[p] = {}
,您可以一次为多个变量分配一个值。你可以做foo = bar = 42
,两人都有42。
您也可以foo = bar = {}
。两者都有指向同一个对象的指针,如果你在一个上更改一个值,另一个就会有更改。
这对于获取和初始化实例
的全局值非常有用var foo = window.foo = window.foo || {bar: 42};
这一行会让foo
和window.foo
在window.foo
上收回对象。如果window.foo
尚未初始化,它将重新获得新对象。