更改对象键和值并保留初始顺序
Changing Object keys & values and preserving the initial order
给出下面的状态对象
{
colour: ['red', 'blue', 'green'],
size: ['small', 'medium', 'large'],
position: ['bottom', 'top', 'left', 'right'],
}
我需要能够change/update它的属性值attrValues
以及属性键attrKey
我正在使用以下逻辑来执行此操作:
setAttributes((prevState) => {
const key = Object.keys(attributeToUpdate)[0];
if (key !== attrKey) {
delete prevState[key];
}
return { ...prevState, [attrKey]: attrValue };
});
如果我将 colour
的属性键更改为 color
它有效,但结果状态更改为:
{
size: ['small', 'medium', 'large'],
position: ['bottom', 'top', 'left', 'right'],
color: ['red', 'blue', 'green'],
}
将color
属性移到末尾,我想保留在原来的位置。
任何帮助或指点将不胜感激。
您无法控制 n 对象中键的顺序 - 如果顺序很重要,您应该有一个对象数组。然后你可以重建删除你想要的项目并替换它的状态。
下面的演示在实践中展示了这一点:
let prevState = [
{key:"colour",values: ['red', 'blue', 'green']},
{key:"size", values:['small', 'medium', 'large']},
{key:"position",values:['bottom', 'top', 'left', 'right']}
]
const indexToRemove = prevState.findIndex(x => x.key == "colour");
prevState = [
...prevState.slice(0,indexToRemove),
{key:"color", values:['red', 'blue', 'green']},
...prevState.slice(indexToRemove+1)
]
console.log(prevState)
所以如果我理解你的代码,更正将是
setAttributes((prevState) => {
const key = Object.keys(attributeToUpdate)[0];
const indexToRemove = prevState.findIndex(x => x.key == key);
return [
...prevState.slice(0,indexToRemove),
{key:attrKey, values:attrValue},
...prevState.slice(indexToRemove+1)
]
});
而且您必须更新其余代码才能使用状态数组而不是对象。
虽然应该考虑到对密钥插入顺序/优先级的担忧,但 OP 正在寻找的解决方案可能接近于下一个提供的代码...
function renamePropertyAndKeepKeyPrecedence(obj, [oldKey, newKey]) {
const descriptors = Object.getOwnPropertyDescriptors(obj);
if (descriptors.hasOwnProperty(oldKey)) {
Object
.entries(descriptors)
.reduce((target, [key, descriptor]) => {
// delete every property.
Reflect.deleteProperty(target, key);
if (key === oldKey) {
// rename addressed key.
key = newKey;
}
// reassign every property.
Reflect.defineProperty(target, key, descriptor)
return target;
}, obj);
}
return obj;
}
const sample = {
position: ['bottom', 'top', 'left', 'right'],
colour: ['red', 'blue', 'green'],
size: ['small', 'medium', 'large'],
};
console.log('before property renaming ...', { sample });
renamePropertyAndKeepKeyPrecedence(sample, ['colour', 'color']);
console.log('after property renaming ...', { sample });
.as-console-wrapper { min-height: 100%!important; top: 0; }
给出下面的状态对象
{
colour: ['red', 'blue', 'green'],
size: ['small', 'medium', 'large'],
position: ['bottom', 'top', 'left', 'right'],
}
我需要能够change/update它的属性值attrValues
以及属性键attrKey
我正在使用以下逻辑来执行此操作:
setAttributes((prevState) => {
const key = Object.keys(attributeToUpdate)[0];
if (key !== attrKey) {
delete prevState[key];
}
return { ...prevState, [attrKey]: attrValue };
});
如果我将 colour
的属性键更改为 color
它有效,但结果状态更改为:
{
size: ['small', 'medium', 'large'],
position: ['bottom', 'top', 'left', 'right'],
color: ['red', 'blue', 'green'],
}
将color
属性移到末尾,我想保留在原来的位置。
任何帮助或指点将不胜感激。
您无法控制 n 对象中键的顺序 - 如果顺序很重要,您应该有一个对象数组。然后你可以重建删除你想要的项目并替换它的状态。
下面的演示在实践中展示了这一点:
let prevState = [
{key:"colour",values: ['red', 'blue', 'green']},
{key:"size", values:['small', 'medium', 'large']},
{key:"position",values:['bottom', 'top', 'left', 'right']}
]
const indexToRemove = prevState.findIndex(x => x.key == "colour");
prevState = [
...prevState.slice(0,indexToRemove),
{key:"color", values:['red', 'blue', 'green']},
...prevState.slice(indexToRemove+1)
]
console.log(prevState)
所以如果我理解你的代码,更正将是
setAttributes((prevState) => {
const key = Object.keys(attributeToUpdate)[0];
const indexToRemove = prevState.findIndex(x => x.key == key);
return [
...prevState.slice(0,indexToRemove),
{key:attrKey, values:attrValue},
...prevState.slice(indexToRemove+1)
]
});
而且您必须更新其余代码才能使用状态数组而不是对象。
虽然应该考虑到对密钥插入顺序/优先级的担忧,但 OP 正在寻找的解决方案可能接近于下一个提供的代码...
function renamePropertyAndKeepKeyPrecedence(obj, [oldKey, newKey]) {
const descriptors = Object.getOwnPropertyDescriptors(obj);
if (descriptors.hasOwnProperty(oldKey)) {
Object
.entries(descriptors)
.reduce((target, [key, descriptor]) => {
// delete every property.
Reflect.deleteProperty(target, key);
if (key === oldKey) {
// rename addressed key.
key = newKey;
}
// reassign every property.
Reflect.defineProperty(target, key, descriptor)
return target;
}, obj);
}
return obj;
}
const sample = {
position: ['bottom', 'top', 'left', 'right'],
colour: ['red', 'blue', 'green'],
size: ['small', 'medium', 'large'],
};
console.log('before property renaming ...', { sample });
renamePropertyAndKeepKeyPrecedence(sample, ['colour', 'color']);
console.log('after property renaming ...', { sample });
.as-console-wrapper { min-height: 100%!important; top: 0; }