【问题标题】:converting formatted json object to array of objects on the same level (flatten) and sum up on each level将格式化的 json 对象转换为同一级别的对象数组(展平)并在每个级别上求和
【发布时间】:2019-11-10 16:59:10
【问题描述】:

有以下树 json 对象:

{
  "Season1": {
    "Title1": {
      "a1": {
        "val1": "100",
        "val2": "200",
        "val3": "300"
      },
      "a2": {
        "val1": "100",
        "val2": "200",
        "val3": "300"
      }
    },
    "Title2": {
      "c1": {
        "val1": "100",
        "val2": "200",
        "val3": "300"
      },
      "d2": {
        "val1": "100",
        "val2": "200",
        "val3": "300"
      }
    }
  }
}

尝试使用以下函数格式化 json:

function Format(obj){
    return Object.entries(obj).flatMap(([key, val]) => {
        let o = { name: key}
        if(Object.keys(val).some(function(k) {return typeof val[k] === 'object'})){
            o['_children'] = Format(val)
        } else {
            Object.keys(val).map(function(a){
                o[a] = val[a]
            })
        }
        return [o]
    })
}

这将通过键返回一个嵌套对象数组:

[
  {
    "name": "Season1",
    "_children": [
      {
        "name": "Title1",
        "_children": [
          {
            "name": "a1",
            "val1": "100",
            "val2": "200",
            "val3": "300"
          },
          {
            "name": "a2",
            "val1": "100",
            "val2": "200",
            "val3": "300"
          }
        ]
      },
      {
        "name": "Title2",
        "_children": [
          {
            "name": "c1",
            "val1": "100",
            "val2": "200",
            "val3": "300"
          },
          {
            "name": "d2",
            "val1": "100",
            "val2": "200",
            "val3": "300"
          }
        ]
      }
    ]
  }
]

挑战在于计算将它们置于同一级别,并在每个父级别递归地添加底层键的小计,即 val1、val2、val3,例如“Title1”、“Title2”和“Season1”,因此在将输出填充到表格后可以填充空白小计单元格。并且子级别应该缩进 4 个空格,具体取决于级别的深度。预期输出应如下所示:

[
  {"name": "Season1", "val1": 600, "val2": 800, "val3": 1200},
  {"name": "    Title1", "val1": 200, "val2": 400, "val3": 600},
  {"name": "        a1", "val1": "100", "val2": "200", "val3": "300"},
  {"name": "        a2", "val1": "100", "val2": "200","val3": "300"},
  {"name": "    Title2","val1": 400, "val2": 400, "val3": 600},
  {"name": "        c1", "val1": "100", "val2": "200", "val3": "300"},
  {"name": "        d2", "val1": "100", "val2": "200", "val3": "300"},
]

如何为此目的更新 Format 函数?有人可以分享任何想法或解决方案吗?谢谢!

【问题讨论】:

  • 如果您打算使用 d3js 处理这些数据,您可以使用 d3js 轻松完成此翻译,而无需编写 vanilajs。

标签: javascript node.js


【解决方案1】:

试试这是否可行!解释代码可能有点棘手。

我在代码的相关部分添加了几个 cmets。

var data = {
  Season1: {
    Title1: {
      a1: {
        val1: "100",
        val2: "150",
        val3: "100"
      },
      a2: {
        val1: "100",
        val2: "200",
        val3: "300"
      }
    },
    Title2: {
      c1: {
        val1: "100",
        val2: "200",
        val3: "300"
      },
      d2: {
        val1: "100",
        val2: "200",
        val3: "300"
      }
    }
  },
  Season2: {
    Title1: {
      a1: {
        val1: "100",
        val2: "200",
        val3: "300"
      },
      a2: {
        val1: "100",
        val2: "200",
        val3: "300"
      }
    },
    Title2: {
      c1: {
        val1: "100",
        val2: "200",
        val3: "300"
      },
      d2: {
        val1: "100",
        val2: "200",
        val3: "300"
      }
    }
  }
};

function Format(obj, depth = 0) {
  return Object.entries(obj).flatMap(([key, val]) => {
    if (
      Object.keys(val).some(function(k) {
        return typeof val[k] === "object";
      })
    ) {
      // Pad keys with spaces based on depth
      let o = {
        name: key.padStart(depth * 4 + key.length)
      };
      const children = Format(val, depth + 1);
      // Get the sum of children that are only only one level deep 
      const childrenSum = children
        .filter(
          ({
            name
          }) =>
          name.length - name.replace(/\s/g, "").length === (depth + 1) * 4
        )
        // Filter out the name key as they are not numbers 
        .reduce((acc, temp) => {
          Object.entries(temp)
            .filter(([key, val]) => key !== "name")
            .forEach(([key, val]) => {
              acc[key] = (acc[key] || 0) + Number(val);
            });
          return acc;
        }, {});
      o = { ...o,
        ...childrenSum
      };
      return [o, ...children];
    } else {
      let o = {
        name: key.padStart(depth * 4 + key.length)
      };
      Object.keys(val).map(function(a) {
        o[a] = val[a];
      });
      return [o];
    }
  });
}

console.log(Format(data));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-29
    • 2011-06-16
    • 2019-07-28
    • 1970-01-01
    相关资源
    最近更新 更多