遍历数组对象,用于嵌套形式
Traverse an object of arrays, for a nested form
我有一个动态的表格,就是嵌套的,表格是描述一个桥式龙门吊。
因此结构如下所示:
let equipmentInfo = {
bridges:[{
trolleys:[{
hoists:[{
}]
}]
}]
}
我为每个桥梁、电车和起重机组设置了一个功能组件。
我传递了一个描述它在树中位置的数组,如:
let keyPath = [['arrayLocation', indexOfEntry]] // [['bridge', 1], ['trolley',3], ['hoist', 0]]
我的问题围绕着这个 getObject 函数的使用
const getObject = (object, location) => {
if(object == undefined) return {}
if(location.length == 0) return object
if(location.length == 1) return object[location[0][0]][location[0][1]]
if(location.length == 2) return object[location[0][0]][location[0][1]][location[1][0]][location[1][1]]
if(location.length == 3) return object[location[0][0]][location[0][1]][location[1][0]][location[1][1]][location[2][0]][location[2][1]]
if(location.length == 4) return object[location[0][0]][location[0][1]][location[1][0]][location[1][1]][location[2][0]][location[2][1]][location[3][0]][location[3][1]]
if(location.length == 5) return object[location[0][0]][location[0][1]][location[1][0]][location[1][1]][location[2][0]][location[2][1]][location[3][0]][location[3][1]][location[4][0]][location[4][1]]
if(location.length == 6) return object[location[0][0]][location[0][1]][location[1][0]][location[1][1]][location[2][0]][location[2][1]][location[3][0]][location[3][1]][location[4][0]][location[4][1]][location[5][0]][location[5][1]]
if(location.length == 7) return object[location[0][0]][location[0][1]][location[1][0]][location[1][1]][location[2][0]][location[2][1]][location[3][0]][location[3][1]][location[4][0]][location[4][1]][location[5][0]][location[5][1]][location[6][0]][location[6][1]]
}
它在 handleOnChange 中的使用如下:
const handleInputChange = (e, keyPath) => {
const { name, value } = e.target;
const object = {...equipmentInfo}
const targetObject = getObject(object, keyPath)
targetObject[name] = value
setObject(targetObject, object, keyPath)
setEquipmentInfo(object);
};
有更好的方法吗?不仅为了更好的可读性,而且为了支持 n 数量的分支。
<BridgeFields
keyPath={newKeypath}
handleOnChange={handleOnChange}
equipmentInfo={EquipmentInfo}
setEquipmentInfo={setEquipentInfo}
/>
实现示例如下:
// inside <BridgeFields/>
getObject(equipmentInfo, keyPath).trolleys.map((trolly, index)) => {
// add to the keyPath the compenent and its index
let newKeyPath = [...keyPath, ["trolleys", index]]
// Form fields describing a bridge
<Form.Component
type='text'
name='serialNumber'
onChange={(e)=>{handleOnChange(e, newKeyPath)}
/>
// also include its child component fields (hoists, etc) .. like:
<HoistFields
keyPath={newKeypath}
handleOnChange={handleOnChange}
equipmentInfo={EquipmentInfo}
setEquipmentInfo={setEquipentInfo}
}
这很有效,而且实际上速度非常快,但我希望改进我在这里所做的工作。这个 equipmentInfo 对象还有更多内容,我想让它变得更好。
感谢任何建议谢谢!
一个可能的解决方案(假设 location
数组将具有确切的键,即 'bridges'、'trolleys'、'hoists')是使用 Array reduce
像这样:
const getObj = (obj = equipmentInfo, location = [['bridges', 1], ['trolleys', 0], ['hoists', 0]]) => (
location.reduce(
(acc, itm) => ({ ... acc[itm[0]][itm[1]] }), obj || {}
)
);
说明
- 对于
location
数组中的每个项目,获取道具(由第 0 个索引指示)。
- prop对应的值是一个数组
- 使用
location
索引 1 处的元素值来标识所需的数组元素(上述步骤 2 中的数组)
抱歉,如果这个解释不太清楚。
要验证的代码片段
const equipmentInfo = {
bridges: [{
trolleys: [{
hoists: [{
k0: 'b0t0h0v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b0t0h1v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b0t0h2v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b0t1h0v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b0t1h1v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b0t1h2v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}]
}, {
trolleys: [{
hoists: [{
k0: 'b1t0h0v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b1t0h1v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b1t0h2v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b1t1h0v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b1t1h1v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b1t1h2v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}]
}]
};
const getObj = (obj = equipmentInfo, location = [
['bridges', 1],
['trolleys', 0],
['hoists', 0]
]) => (
location.reduce(
(acc, itm) => ({ ...acc[itm[0]][itm[1]]
}), obj || {}
)
);
console.log('b 1, t 0, h 0', getObj());
console.log('b 1, t 1, h 0', getObj(equipmentInfo, [
['bridges', 1],
['trolleys', 1],
['hoists', 0]
]));
console.log('b 0, t 1, h 0', getObj(equipmentInfo, [
['bridges', 0],
['trolleys', 1],
['hoists', 0]
]));
console.log('b 0, t 0, h 0', getObj(equipmentInfo, [
['bridges', 0],
['trolleys', 0],
['hoists', 0]
]));
编辑
设置对象代码:
const setObj = (updatedObj, obj = equipmentInfo, location = [
['bridges', 1],
['trolleys', 0],
['hoists', 1]
]) => {
location.reduce((acc, itm, idx) => {
const tgtObj = acc[itm[0]][itm[1]];
if (idx < location.length - 1) return tgtObj;
acc[itm[0]][itm[1]] = {
...tgtObj,
...updatedObj
};
return null;
}, obj);
};
let myObj = {
...equipmentInfo
};
setObj({
zztest: 'okay'
}, myObj);
console.log(myObj);
我有一个动态的表格,就是嵌套的,表格是描述一个桥式龙门吊。
因此结构如下所示:
let equipmentInfo = {
bridges:[{
trolleys:[{
hoists:[{
}]
}]
}]
}
我为每个桥梁、电车和起重机组设置了一个功能组件。 我传递了一个描述它在树中位置的数组,如:
let keyPath = [['arrayLocation', indexOfEntry]] // [['bridge', 1], ['trolley',3], ['hoist', 0]]
我的问题围绕着这个 getObject 函数的使用
const getObject = (object, location) => {
if(object == undefined) return {}
if(location.length == 0) return object
if(location.length == 1) return object[location[0][0]][location[0][1]]
if(location.length == 2) return object[location[0][0]][location[0][1]][location[1][0]][location[1][1]]
if(location.length == 3) return object[location[0][0]][location[0][1]][location[1][0]][location[1][1]][location[2][0]][location[2][1]]
if(location.length == 4) return object[location[0][0]][location[0][1]][location[1][0]][location[1][1]][location[2][0]][location[2][1]][location[3][0]][location[3][1]]
if(location.length == 5) return object[location[0][0]][location[0][1]][location[1][0]][location[1][1]][location[2][0]][location[2][1]][location[3][0]][location[3][1]][location[4][0]][location[4][1]]
if(location.length == 6) return object[location[0][0]][location[0][1]][location[1][0]][location[1][1]][location[2][0]][location[2][1]][location[3][0]][location[3][1]][location[4][0]][location[4][1]][location[5][0]][location[5][1]]
if(location.length == 7) return object[location[0][0]][location[0][1]][location[1][0]][location[1][1]][location[2][0]][location[2][1]][location[3][0]][location[3][1]][location[4][0]][location[4][1]][location[5][0]][location[5][1]][location[6][0]][location[6][1]]
}
它在 handleOnChange 中的使用如下:
const handleInputChange = (e, keyPath) => {
const { name, value } = e.target;
const object = {...equipmentInfo}
const targetObject = getObject(object, keyPath)
targetObject[name] = value
setObject(targetObject, object, keyPath)
setEquipmentInfo(object);
};
有更好的方法吗?不仅为了更好的可读性,而且为了支持 n 数量的分支。
<BridgeFields
keyPath={newKeypath}
handleOnChange={handleOnChange}
equipmentInfo={EquipmentInfo}
setEquipmentInfo={setEquipentInfo}
/>
实现示例如下:
// inside <BridgeFields/>
getObject(equipmentInfo, keyPath).trolleys.map((trolly, index)) => {
// add to the keyPath the compenent and its index
let newKeyPath = [...keyPath, ["trolleys", index]]
// Form fields describing a bridge
<Form.Component
type='text'
name='serialNumber'
onChange={(e)=>{handleOnChange(e, newKeyPath)}
/>
// also include its child component fields (hoists, etc) .. like:
<HoistFields
keyPath={newKeypath}
handleOnChange={handleOnChange}
equipmentInfo={EquipmentInfo}
setEquipmentInfo={setEquipentInfo}
}
这很有效,而且实际上速度非常快,但我希望改进我在这里所做的工作。这个 equipmentInfo 对象还有更多内容,我想让它变得更好。
感谢任何建议谢谢!
一个可能的解决方案(假设 location
数组将具有确切的键,即 'bridges'、'trolleys'、'hoists')是使用 Array reduce
像这样:
const getObj = (obj = equipmentInfo, location = [['bridges', 1], ['trolleys', 0], ['hoists', 0]]) => (
location.reduce(
(acc, itm) => ({ ... acc[itm[0]][itm[1]] }), obj || {}
)
);
说明
- 对于
location
数组中的每个项目,获取道具(由第 0 个索引指示)。 - prop对应的值是一个数组
- 使用
location
索引 1 处的元素值来标识所需的数组元素(上述步骤 2 中的数组)
抱歉,如果这个解释不太清楚。
要验证的代码片段
const equipmentInfo = {
bridges: [{
trolleys: [{
hoists: [{
k0: 'b0t0h0v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b0t0h1v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b0t0h2v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b0t1h0v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b0t1h1v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b0t1h2v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}]
}, {
trolleys: [{
hoists: [{
k0: 'b1t0h0v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b1t0h1v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b1t0h2v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b1t1h0v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b1t1h1v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}, {
hoists: [{
k0: 'b1t1h2v0'
}, {
k1: 'v1'
}, {
k2: 'v2'
}]
}]
}]
};
const getObj = (obj = equipmentInfo, location = [
['bridges', 1],
['trolleys', 0],
['hoists', 0]
]) => (
location.reduce(
(acc, itm) => ({ ...acc[itm[0]][itm[1]]
}), obj || {}
)
);
console.log('b 1, t 0, h 0', getObj());
console.log('b 1, t 1, h 0', getObj(equipmentInfo, [
['bridges', 1],
['trolleys', 1],
['hoists', 0]
]));
console.log('b 0, t 1, h 0', getObj(equipmentInfo, [
['bridges', 0],
['trolleys', 1],
['hoists', 0]
]));
console.log('b 0, t 0, h 0', getObj(equipmentInfo, [
['bridges', 0],
['trolleys', 0],
['hoists', 0]
]));
编辑
设置对象代码:
const setObj = (updatedObj, obj = equipmentInfo, location = [
['bridges', 1],
['trolleys', 0],
['hoists', 1]
]) => {
location.reduce((acc, itm, idx) => {
const tgtObj = acc[itm[0]][itm[1]];
if (idx < location.length - 1) return tgtObj;
acc[itm[0]][itm[1]] = {
...tgtObj,
...updatedObj
};
return null;
}, obj);
};
let myObj = {
...equipmentInfo
};
setObj({
zztest: 'okay'
}, myObj);
console.log(myObj);