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

8

我有一个对象数组。每个对象都有很多键(超过100个),其中一些键可能有特殊字符,我想删除这些字符。

我尝试以以下方式实现:

const result = data.map(datum => {
  const keys = Object.keys(datum)
  const replacedKeys = keys.map(key => {
    const newKey = key.replace(/[.|&;$%@%"<>+]/g, '')
  })
  // ??
})

但我确定这不是正确的方式。

6个回答

5

您可以使用新键映射新对象,并使用Object.assign创建单个对象。

const result = data.map(datum => Object.assign(...Object
    .keys(datum)
    .map(key => ({ [key.replace(/[.|&;$%@%"<>+]/g, '')]: datum[key] }))
));

只是为了让其他人理解输入的内容: 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, }, ]; - Emmanuel Mahuni

3

有了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:

如果还没有实现,这里有一个polyfill:

Object.fromEntries = arr => Object.assign({}, ...arr.map( ([k, v]) => ({[k]: v}) ));

你的 polyfill 不会对具有许多键的大型对象造成问题吗?通常函数可以接受的参数数量是有限制的。 - user6019272
@DoMiNeLa10 "通常函数的参数数量是有限制的"? - guest271314
@DoMiNeLa10 https://dev59.com/U2Eh5IYBdhLWcg3wKQnY#22747268/, https://tc39.github.io/ecma262/#sec-list-and-record-specification-type - guest271314
@guest271314: https://dev59.com/U2Eh5IYBdhLWcg3wKQnY#22747272(这个缺少Safari和其他带有jscore的环境) - user6019272
@DoMiNeLa10之前的评论要求提供当前实现,具有X数量的RAM和N数量的可用磁盘空间。Chromium版本为70+,Firefox版本为65+。你唯一的关于函数参数数量“限制”的来源是SO答案吗?箭头函数是否也适用?你在2019年进行了测试吗?如果是,请问你测试的操作系统是什么?可用的RAM和磁盘空间是多少?你能发布你所进行的测试链接,并列出架构和环境的详细信息吗? - guest271314
显示剩余3条评论

1
这个解决方案依赖于 String.prototype.replace(),因此它可以将StringRegExp作为源,并允许进行替换。请注意,它的性能不是很高,但它仅使用纯函数:

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 可以通过引入可变变量来轻松重写为更快的实现。


1
你可以使用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
);


0
考虑使用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)


0

为了扩展@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,}
];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接