我有一个对象数组。每个对象都有很多键(超过 100 个(,其中一些键可以有我想删除的特殊字符。
我尝试以这种方式做我想做的事:
const result = data.map(datum => {
const keys = Object.keys(datum)
const replacedKeys = keys.map(key => {
const newKey = key.replace(/[.|&;$%@%"<>+]/g, '')
})
// ??
})
但我敢肯定这不是正确的方法。
新键映射新对象,并使用Object.assign
创建单个对象。
const result = data.map(datum => Object.assign(...Object
.keys(datum)
.map(key => ({ [key.replace(/[.|&;$%@%"<>+]/g, '')]: datum[key] }))
));
使用已经在 FireFox 中找到的 ES8 Object.fromEntries
方法,您可以执行以下操作:
const sanitiseKeys = o => Object.fromEntries(Object.entries(o).map(([k,v]) =>
[k.replace(/[.|&;$%@%"<>+]/g,""), v]));
// Example use:
var data = [{ "name#": "John" }, { "@key": 2 }];
data = data.map(sanitiseKeys);
console.log(data);
如果尚未实现,下面是一个 polyfill:
Object.fromEntries = arr => Object.assign({}, ...arr.map( ([k, v]) => ({[k]: v}) ));
此解决方案依赖于 String.prototype.replace()
,因此它可以将 String
s 或 RegExp
s 作为源,并允许替换。请记住,它的性能不是很好,但它只使用纯函数:
const data = {
someKey: 1,
some0Key: 1,
some1Key: 1,
some2Key: 1,
some3Key: 1,
some4Key: 1,
some5Key: 1,
some6Key: 1,
some7Key: 1,
some8Key: 1,
some9Key: 1,
some10Key: 1,
some11Key: 1,
some12Key: 1,
some13Key: 1,
some14Key: 1,
some15Key: 1,
};
// simple equivalent of proposed Object.fromEntries()
const fromEntries = (entries) =>
entries.reduce((obj, [key, value]) => ({
[key]: value,
...obj
}), {});
const replaceObjectKeys = (obj, from, to) =>
fromEntries(
Object.entries(obj)
.map(([key, value]) => [key.replace(from, to), value]));
console.log(replaceObjectKeys(data, /Key$/, 'prop'));
fromEntries
可以很容易地重写为更快的实现,代价是引入可变变量。
JSON.stringify()
将纯JavaScript对象转换为JSON
并使用String.prototype.replace()
匹配有效JSON
的属性,然后使用JSON.parse()
转换回纯JavaScript对象。
从字符类中删除"
,因为有效的JSON
属性被双引号"
括起来。
RegExp
([.|&;$%@%<>+]+)(?=([^1]+|)":)
创建一个包含字符类的捕获组,并匹配字符类,后跟不在字符类中的一个或多个字符,后跟属性名称的右双引号"
后跟冒号字符或双引号后跟冒号字符。
匹配的字符类可以替换为空字符串''
或任何其他字符。
let o = {"a.B|c&D;0$_%@q%<Z>5+":1};
console.log(o);
o = JSON.parse(JSON.stringify(o).replace(/([.|&;$%@%<>+]+)(?=([^1]+|)":)/g, ''));
console.log(
JSON.stringify(o)
, /[.|&;$%@%<>+]+/.test(Object.keys(o)[0]) // false
);
考虑使用 Array#reduce()
聚合输入对象的键的值。这样做的原因是您的密钥清理(即从密钥中删除不需要的字符(可能会导致输入对象的不同键/值对"减少",以便经过净化的键有效地与多个值相关。例如,输入对象如下:
const data = {
'key' : 'value0',
'key&&&' : 'value1',
'key$%<>' : 'value2'
}
将(根据您的卫生条件(生成一个输出对象,其中包含与多个值相关的单个key
:
const data = {
'key' : 'value0', // what about value1, value2 ?
}
要解决此问题,您可以考虑将具有常见清理键的值聚合到数组中,如下所示:
const data = {
'key' : 'value0',
'key&&&' : 'value1',
'key$%<>' : 'value2',
'foo' : 'value3'
}
const result = Object.entries(data).reduce((obj, [ key, value ]) => {
const sanitizedKey = key.replace(/[.|&;$%@%"<>+]/g, '');
const objValue = obj[ sanitizedKey ]
/*
Account for conflicting keys after santizing by grouping
values in a nested array
*/
if(objValue) {
obj[ sanitizedKey ] = [value].concat(objValue)
}
else {
obj[ sanitizedKey ] = value
}
return obj;
}, {});
console.log(result)
为了扩展@Nina的答案,以下是完整的表示:
data = [
{someKey: 1},
{some0Key: 1},
{some1Key: 1,
some2Key: 1},
{some3Key: 1,
some4Key: 1,
some5Key: 1,
some6Key: 1,
some7Key: 1,
some8Key: 1,
some9Key: 1,
some10Key: 1,
},
{some11Key: 1,
some12Key: 1,
some13Key: 1,
some14Key: 1,
some15Key: 1,}
];
result = data.map(datum => Object.assign(...Object
.keys(datum)
.map(key => ({ [key.replace(/some/g, 'bum')]: datum[key] }))
));
结果:
result === [
{bumKey: 1},
{bum0Key: 1},
{bum1Key: 1,
bum2Key: 1},
{bum3Key: 1,
bum4Key: 1,
bum5Key: 1,
bum6Key: 1,
bum7Key: 1,
bum8Key: 1,
bum9Key: 1,
bum10Key: 1,
},
{bum11Key: 1,
bum12Key: 1,
bum13Key: 1,
bum14Key: 1,
bum15Key: 1,}
];