列表

详情


2675. 将对象数组转换为矩阵

编写一个函数,将对象数组 arr 转换为矩阵 m 。

arr 是一个由对象组成的数组或一个数组。数组中的每个项都可以包含深层嵌套的子数组和子对象。它还可以包含数字、字符串、布尔值和空值。

矩阵 m 的第一行应该是列名。如果没有嵌套,列名是对象中的唯一键。如果存在嵌套,列名是对象中相应路径,以点号 "." 分隔。

剩余的每一行对应 arr 中的一个对象。矩阵中的每个值对应对象中的一个值。如果给定对象在给定列中没有值,则应该包含空字符串 ""

矩阵中的列应按 字典升序 排列。

 

示例 1:

输入:
arr = [
  {"b": 1, "a": 2},
  {"b": 3, "a": 4}
]
输出:
[
  ["a", "b"],
  [2, 1],
  [4, 3]
]

解释:
两个对象中有两个唯一的列名:"a"和"b"。 
"a"对应[2, 4]。 
"b"对应[1, 3]。

示例 2:

输入:
arr = [
  {"a": 1, "b": 2},
  {"c": 3, "d": 4},
  {}
]
输出:
[
  ["a", "b", "c", "d"],
  [1, 2, "", ""],
  ["", "", 3, 4],
  ["", "", "", ""]
]

解释:
有四个唯一的列名:"a"、"b"、"c"、"d"。 
 第一个对象具有与"a"和"b"关联的值。 
第二个对象具有与"c"和"d"关联的值。 
第三个对象没有键,因此只是一行空字符串。

示例 3:

输入:
arr = [
  {"a": {"b": 1, "c": 2}},
  {"a": {"b": 3, "d": 4}}
]
输出:
[
  ["a.b", "a.c", "a.d"],
  [1, 2, ""],
  [3, "", 4]
]

解释:
在这个例子中,对象是嵌套的。键表示每个值的完整路径,路径之间用句点分隔。 
有三个路径:"a.b"、"a.c"、"a.d"。

示例 4:

输入:
arr = [
  [{"a": null}],
  [{"b": true}],
  [{"c": "x"}]
]
输出: 
[
  ["0.a", "0.b", "0.c"],
  [null, "", ""],
  ["", true, ""],
  ["", "", "x"]
]

解释:
数组也被视为具有索引为键的对象。 
每个数组只有一个元素,所以键是"0.a"、"0.b"和"0.c"。

示例 5:

输入:
arr = [
  {},
  {},
  {},
]
输出:
[
  [],
  [],
  [],
  []
]

解释:
没有键,所以每一行都是一个空数组。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板

typescript 解法, 执行用时: 476 ms, 内存消耗: 80.8 MB, 提交时间: 2023-05-14 17:07:31

const isObject = (val: unknown): val is object => typeof val === "object" && val !== null;

type DataType = string | number | boolean | null;

function jsonToMatrix(arr: any[]): DataType[][] {
  // 获取所有的 key 和对应的值
  const map = new Map<string, [DataType, number][]>();
  arr.forEach((item, index) => dfs(item, [], index));

  const keys = Array.from(map.keys()).filter(Boolean).sort((a, b) => a.localeCompare(b));

  const n = arr.length;
  const m = keys.length;

  const ans: DataType[][] = Array.from({ length: n + 1 }, () => new Array(m).fill(""));
  ans[0] = keys;

  // 初始化
  for (let i = 0; i < m; i++) {
    // 第一行
    const key = ans[0][i] as string;
    const values = map.get(key)!;
    // 根据 rowIndex 决定放在哪一行
    for (let j = 0; j < values.length; j++) {
      const [value, index] = values[j];
      ans[index + 1][i] = value;
    }
  }

  return ans;

  function dfs(data: object, paths: string[], rowIndex: number) {
    if (!isObject(data)) return;

    const keys = Object.keys(data) as (keyof typeof data)[];
    for (const key of keys) {
      const val = data[key];
      const newPath = paths.concat(key);

      if (isObject(val)) {
        dfs(val, newPath, rowIndex);
      } else {
        const path = newPath.join(".");
        const value = map.get(path) ?? [];
        value.push([val, rowIndex]);
        map.set(path, value);
      }
    }
  }
}

javascript 解法, 执行用时: 344 ms, 内存消耗: 66.3 MB, 提交时间: 2023-05-14 17:07:03

/**
 * @param {Array} arr
 * @return {Matrix}
 */
 
// 先DFS获取第一行的列名(Set去重),再根据列名依次遍历arr取得对应的值。
var jsonToMatrix = function(arr) {
  const s = new Set();
  const getKey = (obj, path = "") => Object(obj) === obj ? Object.keys(obj).forEach(x=>getKey(obj[x], path ? `${path}.${x}` : x)) : s.add(path);
  arr.forEach(x=>getKey(x));
  return arr.reduce((res, x)=>res.push(res[0].map(key=>{
    let o = x;
    for (const k of key.split(".")) {
      if (Object(o) !== o || !(k in o)) return "";
      o = o[k];
    }
    return Object(o) === o ? "" : o;
  })) && res, [[...s].sort()]);
};

上一题