我有一个点号表示的数组,例如:
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"
};
任何帮助将不胜感激。我仅限于
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(还有语义,但是您可以自己转换/转换它们)。您也可以轻松地对其进行多边形填充/填充,请参见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));
在这里,我们希望能够以任何点表示法构建对象,并在其尾部添加初始值。我们将使用拔除方法从参考对象中选择初始值。遍历多个点符号,我们可以创建一个构造对象的数组。只需使用合并方法,我们就可以创建一个目标对象,我们要将构造的对象合并到其中。
我创建了以下代码段,以使用嵌套的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)