javascript - 将点符号字符串转换为对象并查找引用对象
问题描述
我有一个点表示的数组,例如:
var base = ['a.b.c','a.e','h'];
我还有一个参考对象:
var reference = {
a: {
b: {
c:"Hello",
d:"you"
},
e:"beautiful",
f:"and"
},
g:"kind",
h:"World"
};
我需要从基本标记的字符串中构建一个对象并从参考对象中获取值。不幸的是,我无法更改基础或参考。
我让它适用于数组的每个单独部分,但问题是当我尝试合并对象时。它用ae覆盖值abc。
我想要的输出是:
var desiredOutput = {
a: {
b: {
c:"Hello"
},
e:"beautiful"
},
h:"World"
};
但是,使用下面的代码,我的输出是:
var output = {
a: {
e: "beautiful"
},
h: "World"
};
任何帮助,将不胜感激。我仅限于 < ES5,但Object.assign
如果需要,可以使用一些 polyfill。
function convert(base,reference) {
var obj = {};
var getObjectValue = function(string, reference) {
var i = 0;
while (reference && i < string.length) {
reference = reference[string[i++]];
}
return reference;
};
for (var n = 0; n < base.length; n++) {
var s = base[n].split("."),
x = obj;
for(var i = 0; i < s.length-1; i++) {
x = x[s[i]] = {};
}
x[s[i]] = getObjectValue(s,reference);
}
return obj;
}
var base = ['a.b.c','a.e','h'];
var reference = {
a: {
b: {
c:"Hello",
d:"you"
},
e:"beautiful",
f:"and"
},
g:"kind",
h:"World"
};
var desiredOutput = {
a: {
b: {
c:"Hello"
},
e:"beautiful"
},
h:"World"
};
console.log(convert(base,reference));
解决方案
和你的
x = x[s[i]] = {};
s[i]
即使它已经被填充,您也无条件地覆盖该属性。仅当该属性中不存在另一个对象时才分配一个新对象。
if (x[s[i]]) {
x = x[s[i]];
} else {
x = x[s[i]] = {};
}
function convert(base,reference) {
var obj = {};
var getObjectValue = function(string, reference) {
var i = 0;
while (reference && i < string.length) {
reference = reference[string[i++]];
}
return reference;
};
for (var n = 0; n < base.length; n++) {
var s = base[n].split("."),
x = obj;
for(var i = 0; i < s.length-1; i++) {
if (x[s[i]]) {
x = x[s[i]];
} else {
x = x[s[i]] = {};
}
}
x[s[i]] = getObjectValue(s,reference);
}
return obj;
}
var base = ['a.b.c','a.e','h'];
var reference = {
a: {
b: {
c:"Hello",
d:"you"
},
e:"beautiful",
f:"and"
},
g:"kind",
h:"World"
};
var desiredOutput = {
a: {
b: {
c:"Hello"
},
e:"beautiful"
},
h:"World"
};
console.log(convert(base,reference));
这就是我的处理方式:
var base = ['a.b.c','a.e','h'];
var reference = {
a: {
b: {
c:"Hello",
d:"you"
},
e:"beautiful",
f:"and"
},
g:"kind",
h:"World"
};
const results = {};
// Helper function to get the nested value from an array of properties:
const getVal = props => props.reduce((a, b) => a[b], reference);
for (const propStr of base) {
// Turn string into an array of properties:
const props = propStr.split('.');
// Get nested value to assign at the end:
const val = getVal(props);
// Get last property to assign on the last object:
const lastProp = props.pop();
let obj = results;
// Iterate through to the nested object on the `results`,
// creating objects on the way only if they don't exist yet:
while (props.length) {
const prop = props.shift();
if (obj[prop]) obj = obj[prop];
else {
obj[prop] = {};
obj = obj[prop];
}
}
obj[lastProp] = val;
}
console.log(results);
推荐阅读
- python - ModuleNotFoundError:没有名为“abc”的模块
- javascript - 如何使用 js-cookie 在 laravel 5.6 或 JavaScript 上设置动态 cookie
- vim - vim 插件目录优先级
- javascript - 在 Javascript 中寻找一种将具有重复数据的列样式数组转换为对象的方法
- git - 如何将我的项目恢复到以前的版本?[用简单的术语解释。]
- r - 在r中,类向量的顺序在类继承中是否重要
- mysql - 如何替换包含特定文本的 mySQL 列?
- typescript - 打字稿:带有instanceof的条件类型检查未按预期工作
- javascript - 如何让 Vue Router beforeLeave 触发?
- python - 从文本文件创建两个列表