【问题标题】:Use regex to rename keys of array of objects使用正则表达式重命名对象数组的键
【发布时间】:2019-02-09 09:57:12
【问题描述】:

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

我尝试用这种方式做我想做的事:

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

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

【问题讨论】:

    标签: javascript regex


    【解决方案1】:

    此方案依赖String.prototype.replace(),因此可以将Strings 或RegExps 作为源,并允许替换。请记住,它的性能不是很好,但它只使用纯函数:

    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 可以很容易地重写为更快的实现,但代价是引入可变变量。

    【讨论】:

      【解决方案2】:

      您可以使用新键映射新对象并​​使用 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, }, ]; `
      【解决方案3】:

      使用已在 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}) ));
      

      【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            猜你喜欢
            • 2010-12-26
            • 2011-05-31
            • 1970-01-01
            • 1970-01-01
            • 2018-07-30
            • 2011-09-14
            • 2020-01-19
            • 2017-08-10
            • 2020-12-07
            相关资源
            最近更新 更多