使用正则表达式重命名对象数组的键



我有一个对象数组。每个对象都有很多键(超过 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,}
];

最新更新