首页 > 解决方案 > 有没有一种简单的方法可以根据在单个对象的深层嵌套中发现的键模式来拆分深度嵌套的对象数组?

问题描述

假设有一个深度嵌套的对象数组,其中深度是已知的。数组中的所有对象都具有相似的结构。输入数组可能如下所示:

[
  {
    'a': {
        SomeObjectData
    },
    'b': {
        Something Else
    },
    'c': '',
    'd': {
        'e': {
            'f': 'val',
            'g': 'val2',
            'Code[1]': 'asd',
            'Code[2]': 'xyz',
            'CodeDeep[1]': 'qwe',
            'CodeDeep[2]': 'rty',
            'Phoebe[5]': 'rty',
            'h': {
                Some other object data
        }
      }
    }
  },
  {
    'a': {
        SomeObjectData
    },
    'b': {
        Something Else
    },
    'c': '',
    'd_mod': {
        'e': {
            'f': 'val',
            'g': 'val2',
            'h': {
                Some other object data
        }
      }
    }
  },
  {
    'a': {
        SomeObjectData
    },
    'b': {
        Something Else
    },
    'c': '',
    'd': {
        'e': {
            'f': 'val',
            'g': 'val2',
            'CodeDeep[2]': 'rty',
            'h': {
                Some other object data
        }
      }
    }
  }
]

示例中的键 'd' 也可以是 'd_mod',但这不是问题,因为我们可以在遍历时执行 ('d' || 'd_mod')。挑战在于,当遍历 'e' 的值时,我们会在键名中找到一个模式。它可以是任何字母数字,后跟“[someNumber]”。

需要考虑的几件事:如果存在键 Code[1],那么 CodeDeep[1] 也不必存在,反之亦然。可以有尽可能多的键匹配模式。即如果 Code[1] 存在,那么 Code[2] 也可以存在,依此类推。模式中的起始字母将始终存在。即只有 Code[number here] 或 CodeDeep[number here] 中的数字发生变化。键模式中的编号不必总是连续的。也有可能没有这样的匹配,在这种情况下,对象不会被拆分并保持原样。如果嵌套对象“e”中的键模式中的多个键的数量相同,则两个键都进入对象的相同拆分。拆分对象中的键可以与模式相同或去掉 '[number]' 位。

期望的结果:

[
  {
    'a': {
        SomeObjectData
    },
    'b': {
        Something Else
    },
    'c': '',
    'd': {
        'e': {
            'f': 'val',
            'g': 'val2',
            'Code[1]': 'asd',
            'CodeDeep[1]': 'qwe',
            'h': {
                Some other object data
        }
      }
    }
  },
  {
    'a': {
        SomeObjectData
    },
    'b': {
        Something Else
    },
    'c': '',
    'd': {
        'e': {
            'f': 'val',
            'g': 'val2',
            'Code[2]': 'xyz',
            'CodeDeep[2]': 'rty',
            'h': {
                Some other object data
        }
      }
    }
  },
  {
    'a': {
        SomeObjectData
    },
    'b': {
        Something Else
    },
    'c': '',
    'd': {
        'e': {
            'f': 'val',
            'g': 'val2',
            'Phoebe[5]': 'rty',
            'h': {
                Some other object data
        }
      }
    }
  },
  {
    'a': {
        SomeObjectData
    },
    'b': {
        Something Else
    },
    'c': '',
    'd_mod': {
        'e': {
            'f': 'val',
            'g': 'val2',
            'h': {
                Some other object data
        }
      }
    }
  },
  {
    'a': {
        SomeObjectData
    },
    'b': {
        Something Else
    },
    'c': '',
    'd': {
        'e': {
            'f': 'val',
            'g': 'val2',
            'CodeDeep[2]': 'rty',
            'h': {
                Some other object data
        }
      }
    }
  }
]

或没有数字,但其他一切都一样:

[
  {
    'a': {
        SomeObjectData
    },
    'b': {
        Something Else
    },
    'c': '',
    'd': {
        'e': {
            'f': 'val',
            'g': 'val2',
            'Code': 'asd',
            'CodeDeep': 'qwe',
            'h': {
                Some other object data
        }
      }
    }
  },
  {
    'a': {
        SomeObjectData
    },
    'b': {
        Something Else
    },
    'c': '',
    'd': {
        'e': {
            'f': 'val',
            'g': 'val2',
            'Code': 'xyz',
            'CodeDeep': 'rty',
            'h': {
                Some other object data
        }
      }
    }
  },
  {
    'a': {
        SomeObjectData
    },
    'b': {
        Something Else
    },
    'c': '',
    'd': {
        'e': {
            'f': 'val',
            'g': 'val2',
            'Phoebe': 'rty',
            'h': {
                Some other object data
        }
      }
    }
  },
  {
    'a': {
        SomeObjectData
    },
    'b': {
        Something Else
    },
    'c': '',
    'd_mod': {
        'e': {
            'f': 'val',
            'g': 'val2',
            'h': {
                Some other object data
        }
      }
    }
  },
  {
    'a': {
        SomeObjectData
    },
    'b': {
        Something Else
    },
    'c': '',
    'd': {
        'e': {
            'f': 'val',
            'g': 'val2',
            'CodeDeep': 'rty',
            'h': {
                Some other object data
        }
      }
    }
  }
]

两者都是可以接受的,因为在任何情况下,像 Code[1] 和 Code[2] 这样的键都不会按照早期的要求出现在同一个对象中。再次重申主要问题:模式匹配相似编号的键会导致拆分,如果对象中的所有键只有一个数字,则不需要拆分。此外,如果没有模式,则不需要拆分。

我确实设法解决了上面的问题,但我追求的东西看起来不像我的那么乱。

我的尝试:下面采用数组中的单个对象和嵌套属性,然后将其拆分返回嵌套属性拆分数组。

const sameKeyArray = arr => {
    const [rest, ...numbered] = Object.values(Object.entries(arr).reduce((o, [k, v]) => {
      const acc = o;
      const [name, number] = k?.replace('[', '').match(/\D+|\d+\]$/g);
      acc[number] = { ...(acc[number] || {}),
        [name]: v
      };
      return acc;
    }, {}));
    return numbered.map(i => ({ ...i,
      ...rest
    }));
  };

然后我遍历初始输入数组,对于每个项目,我打算使用上面的函数覆盖嵌套属性的值,即我们示例中的“e”从一个字典对象到一个拆分的字典/对象数组。

originalInputArray.map(e => ({ ...e,
    data: { ...e?.data,
      text: { ...e?.data?.text,
        [Object.keys(e?.data?.text)[0]]: { ...e?.data?.text?.['d' || 'd_mod'],
          nested_prop: sameKeyArray(e?.data?.text?.['d' || 'd_mod']?.nested_prop || {})
        }
      }
    }
  }));

请注意,仍然原始项目尚未作为笛卡尔产品退回。只有数组中单个项目的深层嵌套属性已从对象更改为数组。

我再次从上面遍历输入数组,现在已修改。对于每个项目和嵌套属性的长度,我将整个项目与设置为第 i 个元素的嵌套属性一起推送到一个新列表中,这给了我最终的输出。这是最终的遍历代码。

const nested_propSplits = [];
  modifiedInputArray.forEach(e => {
    e.data.text['d' || 'd_mod'].nested_prop.forEach(element => {
      nested_propSplits.push({ ...e,
        data: { ...e?.data,
          text: { ...e?.data?.text,
            [Object.keys(e?.data?.text)[0]]: { ...e?.data?.text?.['d' || 'd_mod'],
              nested_prop: element
            }
          }
        }
      });
    });
  });

如果任何解释不清楚,需要澄清,代码和/或示例与初始要求不一致,请告诉我,我会尽快更新/澄清。欢迎任何建议和很酷的想法。

标签: javascriptnode.jsarraysobjectecmascript-6

解决方案


推荐阅读