我有一个问题,要根据给定的数组对象动态向下移动对象。
尝试了一些静态代码,但这在存在更多或更少级别的情况下不灵活
// value = 10
// field = ["data", "input", "level", "0"]
item[field[0]][field[1]][field[2]][field[3]] = value
我不知道从哪里开始使用for循环执行此功能。有人可以给我一些建议开始吗?
答案 0 :(得分:2)
您可以缩小字段并获取一个对象及其属性。最后,用最后一个键分配值。
const
setValue = (object, [...path], value) => {
var last = path.pop();
path.reduce((o, k) => o[k] = o[k] || {}, object)[last] = value;
},
object = {},
value = 10,
fields = ["data", "input", "level", "0"];
setValue(object, fields, value);
console.log(object);
答案 1 :(得分:1)
Lodash上有一个内置方法可以执行此操作-how to load their tools asynchronously。
_.set(item, field, value)
let item = {
data: {
input: {
level: [5]
}
}
};
const field = ["data", "input", "level", "0"];
const value = 10;
_.set(item, field, value);
console.log(item);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
答案 2 :(得分:0)
您可以保留一个current
变量,该变量代表对象中当前所在的对象,然后在循环完成后在最后设置值:
const item = {
"data": {
"input": {
"level": {
0: -1
}
}
}
}
let value = 10;
let field = ["data", "input", "level", "0"];
let current = item[field[0]];
for (let i = 1; i < field.length - 1; i++) {
current = current[field[i]];
}
current[field.pop()] = value;
console.log(item);
上述操作也可以递归实现(如果存在伪造的字段值,请使用nf === undefined
而不是!nf
)
const item = {
"data": {
"input": {
"level": {
0: -1
}
}
}
}
let value = 10;
let field = ["data", "input", "level", "0"];
const set_val = (val, obj, [f, nf, ...rest]) =>
!nf ? obj[f] = val : set_val(val, obj[f], [nf, ...rest]);
set_val(value, item, field);
console.log(item);
如果您希望从头开始构建item
对象,也可以这样做:
const value = 10;
const field = ["data", "input", "level", "0"];
let item = {};
let curr = item;
for (let i = 0; i < field.length - 1; i++) {
curr[field[i]] = {};
curr = curr[field[i]];
}
curr[field.pop()] = value;
console.log(item);
此构建也可以像这样递归完成:
const value = 10;
const field = ["data", "input", "level", "0"];
let item = {};
let curr = item;
const set_val = (val, [f, nf, ...rest], item = {}) => {
if (!nf) {
item[f] = val;
return item;
} else {
item[f] = set_val(val, [nf, ...rest], item[f]);
return item;
}
}
console.log(set_val(value, field));
答案 3 :(得分:0)
您可以使用递归函数浏览对象:
var value = 10;
var field = ["data", "input", "level", "0"];
var obj =
{
data:
{
input:
{
level: [42]
}
}
};
function SetValue(field, obj, value, index = 0)
{
var memberName = field[index];
// not at last item ?
if (index < field.length - 1)
{
if (obj.hasOwnProperty(memberName))
{
SetValue(field, obj[memberName], value, index + 1);
}
}
else
{
obj[memberName] = value;
}
}
console.log("Before");
console.log(obj);
console.log("---------------------");
SetValue(field, obj, value);
console.log("After");
console.log(obj);
console.log("---------------------");
答案 4 :(得分:0)
我已经在生产环境中使用了一个函数,该函数实际上可以实现您想要的:
/**
* Replace an item in datasource with specified path with new value.
* Will _create_ an item if the path does not currently exist.
* @param {object} o Datasource
* @param {array} k Array of keys used to access item (usually getPath())
* @param {*} v New value of specified item
*/
const replaceItem = (o, k, v) => k.reduce((r, e, i, a) => {
if (!a[i + 1]) r[e] = v;
else return r[e]
}, o)
const dataSource = {
data: {
input: {
level: [1]
}
}
}
const path = ["data", "input", "level", "0"]
replaceItem(dataSource, path, 5)
console.log(dataSource)
答案 5 :(得分:0)
另一种版本,略有不同。它区分创建的对象是Object
还是Array
const setValue = (object, path, value) => {
if (!object || !path || !path.length) return;
var key = path[0],
i = 1,
prev = key;
while (i < path.length) {
key = path[i++];
object = object[prev] || (object[prev] = +key === (key >>> 0) ? [] : {});
prev = key;
}
object[key] = value;
};
const object = {};
setValue(object, ["data", "input", "level", "0"], 10);
console.log(object);