将点表示法字符串转换为对象并查找引用对象



我有一个带点标记的数组,例如:

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(和语义,但你可以自己转换/转译(。您也可以轻松地填充/小马填充它,请参阅本文。

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)

试试这个:

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;
}

最新更新