【问题标题】:How to replace key in nested object如何替换嵌套对象中的键
【发布时间】:2019-10-24 03:23:32
【问题描述】:

我有一个这样的对象,

{
  id: '1',
  displaName: 'A',
  children: [
  {
    id: '2',
    displayName: 'B',
    children: [
    {
      id: '3',
      displayName: 'C',
      children: [
            //More nested array here
      ]
    }
    ]
  }]
}

我只想将键 displayName 更改为 label,以便我的对象看起来像这样,

{
  id: '1',
  label: 'A',  //change key displayName => label
  children: [
  {
    id: '2',
    label: 'B',  //change key displayName => label
    children: [
    {
      id: '3',
      label: 'C',  //change key displayName => label
      children: [
            //More nested array here
      ]
    }
    ]
  }]
}

我已经尝试过了,但无法替换嵌套数组中的键,

const newKeys = { displaName: "label"};
const renamedObj = renameKeys(resp.data, newKeys);
console.log(renamedObj);

function renameKeys(obj, newKeys) {
  const keyValues = Object.keys(obj).map(key => {
    console.log(key);
    let newKey = null
    if(key === 'displayName'){
       newKey = 'label'
    }else{
       newKey = key
    }
    console.log(newKey);
    return { [newKey]: obj[key] };
  });
  return Object.assign({}, ...keyValues);
}

请帮我解决这个问题。

提前致谢。

【问题讨论】:

    标签: javascript javascript-objects


    【解决方案1】:
    1. 您的代码中有错字。一些变量显示为displaName,而不是displayName。

    2. 您需要递归调用函数才能按预期工作。

    3. 您没有使用 newKeys 变量进行重命名。您只是像newKey = 'label' 一样对其进行了硬编码。但是这个问题与问题无关。

    const resp = {
      data: {
        id: '1',
        displayName: 'A',
        children: [{
          id: '2',
          displayName: 'B',
          children: [{
            id: '3',
            displayName: 'C',
            children: [
              //More nested array here
            ]
          }]
        }]
      }
    }
    
    const newKeys = {
      displayName: "label"
    };
    const renamedObj = this.renameKeys(resp.data, newKeys);
    console.log(renamedObj);
    
    function renameKeys(obj, newKeys) {
      const keyValues = Object.keys(obj).map(key => {
        let newKey = null
        if (key === 'displayName') {
          newKey = newKeys.displayName
        } else {
          newKey = key
        }
        if (key === 'children') {
          obj[key] = obj[key].map(obj => renameKeys(obj, newKeys));    
        }
        return {
          [newKey]: obj[key]
        };
      });
      return Object.assign({}, ...keyValues);
    }

    【讨论】:

      【解决方案2】:

      这是一个非常通用的解决方案,它将遍历对象并更新给定对象文字 (keysToUpdate) 中的任何对象键。

      const orig = {
        id: '1',
        displayName: 'A',
        children: [{
          id: '2',
          displayName: 'B',
          children: [{
            id: '3',
            displayName: 'C',
            children: [
              //More nested array here
            ]
          }]
        }]
      };
      
      const updateDisplayNameToLabel = (val, keysMap) => {
        if (val == null) return null;
        if (Array.isArray(val)) {
          return val.map(item => updateDisplayNameToLabel(item, keysMap));
        } else if (typeof val == "object") {
          return Object.keys(val).reduce((obj, key) => {
            const propKey = updateDisplayNameToLabel(key, keysMap);
            const propVal = updateDisplayNameToLabel(val[key], keysMap);
            obj[propKey] = propVal;
            return obj;
          }, {});
        } else if (typeof val === "string") {
          return keysMap[val] || val;
        }
        return val;
      }
      
      const keysToUpdate = {
        displayName: 'label',
        children: 'items'
      };
      
      const updated = updateDisplayNameToLabel(orig, keysToUpdate);
      
      console.log(updated);

      【讨论】:

        【解决方案3】:

        现有的答案很棒,但我忍不住添加了JSON.stringify 版本:

        const data = { id: '1', displayName: 'A', children: [ { id: '2', displayName: 'B', children: [ { id: '3', displayName: 'C', children: [] }] }] };
        const result = JSON.parse(JSON.stringify(data).replace(/"displayName":/g, '"value":'));
        console.log(result);

        显然,如果您有一个看起来像键的值,这将不起作用,因此它假定您有可预测数据的保证。

        如果你有多个替换,你可以使用

        const data = { id: '1', displayName: 'A', children: [ { id: '2', displayName: 'B', children: [ { id: '3', displayName: 'C', children: [] }] }] };
        const swaps = {displayName: "foo", children: "baz", id: "corge"};
        const pattern = new RegExp(
          Object.keys(swaps).map(e => `(?:"(${e})":)`).join("|"), "g"
        );
        const result = JSON.parse(
          JSON.stringify(data).replace(pattern, m => `"${swaps[m.slice(1,-2)]}":`)
        );
        console.log(result);

        更传统的递归选项可能如下(仍然假设/硬编码children):

        const changeKey = (node, keySubs) => 
          Object.entries(keySubs).reduce((a, [oldKey, newKey]) => {
            a[newKey] = a[oldKey];
            delete a[oldKey];
            return a;
          }, {...node, children: node.children.map(e => changeKey(e, keySubs))})
        ;
        
        const data = { id: '1', displayName: 'A', children: [ { id: '2', displayName: 'B', children: [ { id: '3', displayName: 'C', children: [] }] }] };
        const swaps = {displayName: "label", id: "better id"};
        console.log(changeKey(data, swaps));

        迭代:

        const changeKey = (node, keySubs) => {
          const result = {children: []};
          const stack = [[node, result]];
        
          while (stack.length) {
            const [curr, parent] = stack.pop();
            const child = Object.entries(keySubs)
              .reduce((a, [oldKey, newKey]) => {
                a[newKey] = a[oldKey];
                delete a[oldKey];
                return a;
              }, {...curr, children: []})
            ;
            parent.children.push(child);
            stack.push(...curr.children.map(e => [e, child]));
          }
        
          return result;
        };
        
        const data = { id: '1', displayName: 'A', children: [ { id: '2', displayName: 'B', children: [ { id: '3', displayName: 'C', children: [] }] }] };
        const swaps = {displayName: "label", id: "better id"};
        console.log(changeKey(data, swaps));

        【讨论】:

          猜你喜欢
          • 2021-12-11
          • 2022-10-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-26
          • 1970-01-01
          相关资源
          最近更新 更多