将点符号字符串转换为对象和查找引用对象
Convert dot notation string to object and lookup reference object
我有一个点符号数组,例如:
var base = ['a.b.c','a.e','h'];
我还有一个参考对象:
var reference = {
a: {
b: {
c:"Hello",
d:"you"
},
e:"beautiful",
f:"and"
},
g:"kind",
h:"World"
};
我需要用基本标记字符串构建一个对象,并从引用对象中获取值。不幸的是,我无法更改基础或参考。
我让它为数组的每个单独部分工作,但问题是当我尝试合并对象时。它用 a.e.
覆盖值 a.b.c
我想要的输出是:
var desiredOutput = {
a: {
b: {
c:"Hello"
},
e:"beautiful"
},
h:"World"
};
但是,使用下面的代码,我的输出是:
var output = {
a: {
e: "beautiful"
},
h: "World"
};
如有任何帮助,我们将不胜感激。我仅限于 < ES5,但如果需要可以使用一些 polyfill,例如 Object.assign
。
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);
这可以在没有 while 循环的情况下实现!
我只使用了 es6 的 Array.prototype.reduce(和语义,但你可以 convert/transpile 你自己)。你也可以轻松poly/ponyfill它,见this article.
const base = ['a.b.c', 'a.e', 'h'];
const reference = {
a: {
b: {
c: 'Hello',
d: 'you'
},
e: 'beautiful',
f: 'and'
},
g: 'kind',
h: 'World'
};
const isObject = item => (item && typeof item === 'object' && !Array.isArray(item) && item !== null);
const pick = (obj, keys) => keys.split('.').reduce((prev, key) => {
const ret = (prev || obj);
if (isObject(ret) && key in ret) {
return ret[key];
}
return prev;
}, null);
const extend = (target, source) => {
if (isObject(target) && isObject(source)) {
Object.keys(source).forEach((key) => {
if (isObject(source[key])) {
if (!target[key] || !isObject(target[key])) {
target[key] = source[key];
}
extend(target[key], source[key]);
} else {
Object.assign(target, { [key]: source[key] });
}
});
}
return target || source;
};
const fromDotNotation = (dotNotation, value) => {
const ret = {};
dotNotation.split('.').reduce((prev, key, i, self) => {
return prev[key] = (i === self.length - 1) ? value : prev[key] || {};
}, ret);
return ret;
}
const fromDotNotations = (source, dotNotations) => dotNotations.reduce((prev, dotNotation) => {
return extend(prev, fromDotNotation(dotNotation, pick(source, dotNotation)));
}, {});
const output = fromDotNotations(reference, base);
console.log(JSON.stringify(output, null, 2));
在这里,我们希望能够从任何点符号构建一个对象,其尾部有一个初始值。我们将使用 plucking 方法从参考对象中选取初始值。遍历多个点符号,我们可以创建一个构造对象数组。简单地使用合并方法,我们可以创建一个目标对象,我们想要将我们构造的对象合并到其中。
我创建了以下代码片段以使用嵌套的 foreach 以简单的方式获得您想要的结果,希望这对您有所帮助。我在评论中描述了代码。
var reference = {
a: {
b: {
c: "Hello",
d: "you"
},
e: "beautiful",
f: "and"
},
g: "kind",
h: "World"
};
var base = ['a.b.c', 'a.e', 'h'];
var result = {};
base.forEach(str => {
//split the base by `.`
var arr = str.split('.');
//get the value
var val = arr.reduce((r, el) => r[el], reference);
//set the initial temporary path of resulting object
var tmp = result;
arr.forEach((el, i) => {
//set final property value into resulting object
if (i == arr.length - 1)
return tmp[el] = val;
//create nested property in resulting object
if (!tmp[el])
tmp[el] = {};
//update temporary path
tmp = tmp[el];
});
});
console.log(result)
试试这个:
deepLookup(input, targetObj) {
const nsList = input.split('.');
let found = targetObj;
nsList.forEach(ns => {
if (found.hasOwnProperty(ns)) {
found = found[ns];
} else {
found = null;
}
});
return found;
}
我有一个点符号数组,例如:
var base = ['a.b.c','a.e','h'];
我还有一个参考对象:
var reference = {
a: {
b: {
c:"Hello",
d:"you"
},
e:"beautiful",
f:"and"
},
g:"kind",
h:"World"
};
我需要用基本标记字符串构建一个对象,并从引用对象中获取值。不幸的是,我无法更改基础或参考。
我让它为数组的每个单独部分工作,但问题是当我尝试合并对象时。它用 a.e.
覆盖值 a.b.c我想要的输出是:
var desiredOutput = {
a: {
b: {
c:"Hello"
},
e:"beautiful"
},
h:"World"
};
但是,使用下面的代码,我的输出是:
var output = {
a: {
e: "beautiful"
},
h: "World"
};
如有任何帮助,我们将不胜感激。我仅限于 < ES5,但如果需要可以使用一些 polyfill,例如 Object.assign
。
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);
这可以在没有 while 循环的情况下实现!
我只使用了 es6 的 Array.prototype.reduce(和语义,但你可以 convert/transpile 你自己)。你也可以轻松poly/ponyfill它,见this article.
const base = ['a.b.c', 'a.e', 'h'];
const reference = {
a: {
b: {
c: 'Hello',
d: 'you'
},
e: 'beautiful',
f: 'and'
},
g: 'kind',
h: 'World'
};
const isObject = item => (item && typeof item === 'object' && !Array.isArray(item) && item !== null);
const pick = (obj, keys) => keys.split('.').reduce((prev, key) => {
const ret = (prev || obj);
if (isObject(ret) && key in ret) {
return ret[key];
}
return prev;
}, null);
const extend = (target, source) => {
if (isObject(target) && isObject(source)) {
Object.keys(source).forEach((key) => {
if (isObject(source[key])) {
if (!target[key] || !isObject(target[key])) {
target[key] = source[key];
}
extend(target[key], source[key]);
} else {
Object.assign(target, { [key]: source[key] });
}
});
}
return target || source;
};
const fromDotNotation = (dotNotation, value) => {
const ret = {};
dotNotation.split('.').reduce((prev, key, i, self) => {
return prev[key] = (i === self.length - 1) ? value : prev[key] || {};
}, ret);
return ret;
}
const fromDotNotations = (source, dotNotations) => dotNotations.reduce((prev, dotNotation) => {
return extend(prev, fromDotNotation(dotNotation, pick(source, dotNotation)));
}, {});
const output = fromDotNotations(reference, base);
console.log(JSON.stringify(output, null, 2));
在这里,我们希望能够从任何点符号构建一个对象,其尾部有一个初始值。我们将使用 plucking 方法从参考对象中选取初始值。遍历多个点符号,我们可以创建一个构造对象数组。简单地使用合并方法,我们可以创建一个目标对象,我们想要将我们构造的对象合并到其中。
我创建了以下代码片段以使用嵌套的 foreach 以简单的方式获得您想要的结果,希望这对您有所帮助。我在评论中描述了代码。
var reference = {
a: {
b: {
c: "Hello",
d: "you"
},
e: "beautiful",
f: "and"
},
g: "kind",
h: "World"
};
var base = ['a.b.c', 'a.e', 'h'];
var result = {};
base.forEach(str => {
//split the base by `.`
var arr = str.split('.');
//get the value
var val = arr.reduce((r, el) => r[el], reference);
//set the initial temporary path of resulting object
var tmp = result;
arr.forEach((el, i) => {
//set final property value into resulting object
if (i == arr.length - 1)
return tmp[el] = val;
//create nested property in resulting object
if (!tmp[el])
tmp[el] = {};
//update temporary path
tmp = tmp[el];
});
});
console.log(result)
试试这个:
deepLookup(input, targetObj) {
const nsList = input.split('.');
let found = targetObj;
nsList.forEach(ns => {
if (found.hasOwnProperty(ns)) {
found = found[ns];
} else {
found = null;
}
});
return found;
}