高级农民
- 积分
- 4143
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2017-1-22
- 最后登录
- 1970-1-1
|
2675. Array of Objects to Matrix
Hard
Hint
Write a function that converts an array of objects arr into a matrix m.
arr is an array of objects or arrays. Each item in the array can be deeply nested with child arrays and child objects. It can also contain numbers, strings, booleans, and null values.
The first row m should be the column names. If there is no nesting, the column names are the unique keys within the objects. If there is nesting, the column names are the respective paths in the object separated by ".".
Each of the remaining rows corresponds to an object in arr. Each value in the matrix corresponds to a value in an object. If a given object doesn't contain a value for a given column, the cell should contain an empty string "".
The columns in the matrix should be in lexographically ascending order.
Example 1:
Input:
arr = [
{"b": 1, "a": 2},
{"b": 3, "a": 4}
]
Output:
[
["a", "b"],
[2, 1],
[4, 3]
]
Explanation:
There are two unique column names in the two objects: "a" and "b".
"a" corresponds with [2, 4].
"b" coresponds with [1, 3].
Example 2:
Input:
arr = [
{"a": 1, "b": 2},
{"c": 3, "d": 4},
{}
]
Output:
[
["a", "b", "c", "d"],
[1, 2, "", ""],
["", "", 3, 4],
["", "", "", ""]
]
Explanation:
There are 4 unique column names: "a", "b", "c", "d".
The first object has values associated with "a" and "b".
The second object has values associated with "c" and "d".
The third object has no keys, so it is just a row of empty strings.
Example 3:
Input:
arr = [
{"a": {"b": 1, "c": 2}},
{"a": {"b": 3, "d": 4}}
]
Output:
[
["a.b", "a.c", "a.d"],
[1, 2, ""],
[3, "", 4]
]
Explanation:
In this example, the objects are nested. The keys represent the full path to each value separated by periods.
There are three paths: "a.b", "a.c", "a.d".
Example 4:
Input:
arr = [
[{"a": null}],
[{"b": true}],
[{"c": "x"}]
]
Output:
[
["0.a", "0.b", "0.c"],
[null, "", ""],
["", true, ""],
["", "", "x"]
]
Explanation:
Arrays are also considered objects with their keys being their indices.
Each array has one element so the keys are "0.a", "0.b", and "0.c".
Example 5:
Input:
arr = [
{},
{},
{},
]
Output:
[
[],
[],
[],
[]
]
Explanation:
There are no keys so every row is an empty array.
Constraints:
arr is a valid JSON array
1 <= arr.length <= 1000
unique keys <= 1000
这道题的核心任务是将一个深度嵌套的 JSON 数组“拍平”(Flatten),并转换成一个类似 Excel 表格的二维数组(矩阵)。
核心解题思路
要完成这个转换,我们可以分为四个步骤:
递归扁平化 (Flatten):
原数据里可能有对象嵌套对象,或者数组嵌套对象。我们需要写一个递归函数,把深度嵌套的结构拍平。
如果遇到的是对象或数组,就提取它的键(或索引),然后和父级的路径用 . 拼接(例如从 { a: { b: 1 } } 变成 "a.b": 1)。
如果遇到的是基本数据类型(数字、字符串、布尔值、null),说明到底了,直接把它存入一个只有一层的一维对象中。
收集并去重表头:
在扁平化的过程中,我们用一个 Set 把所有出现过的路径(列名)收集起来,确保没有重复。
字典序排序:
题目要求列名必须按字母顺序(字典序)排列。我们将 Set 转换成数组,直接使用 JavaScript 原生的 .sort() 方法即可得到矩阵的第一行(表头)。
填充数据,生成矩阵:
把排序好的表头作为矩阵的第 0 行。然后遍历我们拍平后的每一个对象:对照着表头,如果对象里有这个键,就填入对应的值;如果没有,就填入空字符串 ""。- type JSONValue = null | boolean | number | string | JSONValue[] | { [key: string]: JSONValue };
- function jsonToMatrix(arr: JSONValue[]): (null | boolean | number | string)[][] {
- // 存放拍平后的每一个对象
- const flattenedArr: Record<string, null | boolean | number | string>[] = [];
- const keySet = new Set<string>();
- // 递归辅助函数
- function flatten(val: JSONValue, path: string, result: Record<string, null | boolean | number | string>) {
- if (val !== null && typeof val === 'object') {
- const keys = Object.keys(val);
- for (const key of keys) {
- // 如果当前已经有路径了,就用 '.' 拼接;如果是第一层,直接用 key
- const newPath = path ? `${path}.${key}` : key;
- flatten((val as any)[key], newPath, result);
- }
- } else {
- // 【修复报错的位置】使用 as 断言,向 TS 保证这里绝对是基本类型或 null
- result[path] = val as null | boolean | number | string;
- }
- }
- // 1. 遍历并拍平根数组中的每一个元素
- for (const item of arr) {
- const flat: Record<string, null | boolean | number | string> = {};
- flatten(item, "", flat);
- flattenedArr.push(flat);
-
- // 2. 将当前对象的所有路径加入 Set 中
- for (const key of Object.keys(flat)) {
- keySet.add(key);
- }
- }
- // 3. 对所有列名进行字典序排序
- const sortedKeys = Array.from(keySet).sort();
-
- // 4. 构建最终的矩阵,第一行是排好序的表头
- const matrix: (null | boolean | number | string)[][] = [sortedKeys];
-
- // 遍历拍平后的对象数组,按表头的顺序填充每一行
- for (const flat of flattenedArr) {
- const row: (null | boolean | number | string)[] = [];
- for (const key of sortedKeys) {
- // 如果该对象包含这个键,填入值;否则填入空字符串
- if (flat.hasOwnProperty(key)) {
- row.push(flat[key]);
- } else {
- row.push("");
- }
- }
- matrix.push(row);
- }
-
- return matrix;
- }
复制代码 |
|