【问题标题】:Decoding nested objects in Javascript在 Javascript 中解码嵌套对象
【发布时间】:2021-11-02 23:39:32
【问题描述】:

我需要将对象 input 解码为对象 output,如下所示:

let input = {
         a : 'b',
        'c.d': 'e',
        'c.f': 'g',
        'c.h.0':'i',
        'c.h.1':'j',
        'c.h.2':'k'
}

let output = {
    a : 'b',
    c: {
       d: 'e',
       f:'g',
       h: ['i', 'j', 'k']
     }
    }

我有这个解码功能,除了数组,它工作得很好。如何更改此函数以也支持数组解码,并返回上述输出对象

function assembleQueryData(input) {
  const output = {};

  const keys = Object.keys(input);

  for (let i = 0; i < keys.length; i++) {
    const key = keys[i];
    const dots = key.split(".");

    let last = output;
    for (let j = 0; j < dots.length; j++) {
      const dot = dots[j];
      if (j >= dots.length - 1) {
        last[dot] = input[key];
      } else {
        last[dot] = last[dot] || {};
      }
      last = last[dot];
    }
  }
  console.log(output);
  return output;
}

【问题讨论】:

  • 不得不提一下,d: 'e,的代码有错别字,应该是d: 'e',
  • 输入的是字符串吗?
  • 嘿,代码无法运行,我不得不将对象键与' 类似:'c.d': 'g',并且不得不将input.keys 替换为Object.keys(input),您能改进代码吗?你可以把它作为你的问题中的可执行文件
  • 我已经修复了代码

标签: javascript node.js arrays javascript-objects decoding


【解决方案1】:

let input = {
   a : 'b',
   'c.d': 'e',
   'c.f': 'g',
   'c.h.0': 'i',
   'c.h.1': 'j',
   'c.h.2': 'k',
   'l.m.0': 'n',
   'l.m.1': 'o',
   'l.m.2': 'p',
   'l.m.q': 'r',
}

const assembleQueryData = (input) => {
  const output = {}
  const keys = Object.keys(input)

  for (let i = 0; i < keys.length; i++) {
    const key = keys[i]
    const dots = key.split('.')

    let parent = null;
    let last = output
    for (let j = 0; j < dots.length; j++) {
      const dot = dots[j]
      if (j >= dots.length - 1) {
        if (!/^\d+$/.test(dot) && Array.isArray(last)) {
          last = Object.fromEntries(last.map((value, i) => [i, value]));
          parent[dots[j - 1]] = last
        }
        last[dot] = input[key]
      } else {
        last[dot] = last[dot] || (/^\d+$/.test(dots[j + 1]) ? [] : {})
      }
      parent = last
      last = last[dot]
    }
  }

  return output
}

console.log(assembleQueryData(input));

【讨论】:

  • 谢谢,它很好用,但是有 'c.h.0' 、 'c.h.1' 、 'c.h.2' 和 'c.h.a' 怎么样。我认为在这种情况下(当当前键的所有后缀都不是数字时)代码应该检测到它不是数组并将其解码为对象。
  • @MahsaShadi 希望在新版本中得到修复。
【解决方案2】:

我认为没有一种简单的方法可以一次性涵盖所有情况,在此解决方案中,我们首先创建给定输入的对象表示,然后用我们认为适合深度的数组替换该对象-第一次横向,我们这里也负责创建适当的数组。

let input = {
  'a': 'b',
  'c.d': 'e',
  'c.f': 'g',
  'c.h.0': 'i',
  'c.h.1': 'j',
  'c.h.2': 'k',
  'c.k.0': 'i',
  'c.h.a': 'j',
  'c.p.0.5.c': 'j',
  'd.1': {},
  'd.1.6':'cat'
}

console.log(input)

const assembleQueryData = (input) => {
  return Object.entries(input).reduce((obj, [key, value]) => {
    let keySet = key.split('.');
    keySet.reduce((p, k, i) => {
      if (keySet.length === (i + 1)) { p[k] = value; }
      else { p[k] = p[k] || {}; }
      return p[k]
    }, obj);
    return obj;
  }, {});
}

isObjectOrArray = (input) => {
  return Array.isArray(input) || typeof input === 'object' && input !== null;
}

// recursive array which get array if object is array
const getArrays = (input) => {
  if (!isObjectOrArray(input)) {
    return input;
  }

  let isArray =  Array.isArray(input);
  if (!isArray) {
    let isArray = !Object.keys(input).some(k => isNaN(k));
    if (isArray) {
      let len =  Math.max(...Object.keys(input))
      let arr = Array(len + 1).fill(undefined);
      input = arr.map((v, i) => input[i]);
    }
  }

  Object.entries(input).forEach(([key, value]) => {
    input[key] = getArrays(value);
  });
  return input
}

let objOutput = assembleQueryData(input)
let output = getArrays(objOutput)
console.log(output)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-15
    • 2015-04-23
    • 1970-01-01
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    相关资源
    最近更新 更多