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 = [ {}, {}, {}, ] 输出: [ [], [], [], [] ] 解释: 没有键,所以每一行都是一个空数组。
提示:
1 <= arr.length <= 1000
unique keys <= 1000
原站题解
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()]); };