Repository navigation
Expand file tree
/
Copy pathobjectToMatrix.js
More file actions
133 lines (112 loc) · 3.41 KB
/
Copy pathobjectToMatrix.js
File metadata and controls
133 lines (112 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* Converts an array of objects into a matrix format.
* @param {Array} arr - Array of objects or arrays to convert
* @returns {Array} Matrix where first row contains column headers and subsequent rows contain values
*/
function objectToMatrix(arr) {
if (!arr || arr.length === 0) {
return [[]];
}
// Step 1: Collect all possible column paths from all objects
const allPaths = new Set();
for (const item of arr) {
const paths = getAllPaths(item);
paths.forEach(path => allPaths.add(path));
}
// Step 2: Sort column names lexicographically
const sortedColumns = Array.from(allPaths).sort();
// Step 3: Create the matrix
const matrix = [];
// First row: column headers
matrix.push(sortedColumns);
// Subsequent rows: values for each object
for (const item of arr) {
const flattenedObj = flattenObject(item);
const row = sortedColumns.map(column =>
flattenedObj.hasOwnProperty(column) ? flattenedObj[column] : ""
);
matrix.push(row);
}
return matrix;
}
/**
* Gets all possible paths in an object or array
* @param {*} obj - Object or array to traverse
* @param {string} prefix - Current path prefix
* @returns {Array} Array of all paths
*/
function getAllPaths(obj, prefix = "") {
const paths = [];
if (obj === null || typeof obj !== "object") {
// Primitive value - add the current path if it exists
if (prefix) {
paths.push(prefix);
}
return paths;
}
if (Array.isArray(obj)) {
// Handle arrays
for (let i = 0; i < obj.length; i++) {
const currentPath = prefix ? `${prefix}.${i}` : `${i}`;
const subPaths = getAllPaths(obj[i], currentPath);
paths.push(...subPaths);
}
} else {
// Handle objects
const keys = Object.keys(obj);
if (keys.length === 0) {
// Empty object - no paths to add
return paths;
}
for (const key of keys) {
const currentPath = prefix ? `${prefix}.${key}` : key;
const subPaths = getAllPaths(obj[key], currentPath);
if (subPaths.length === 0) {
// This is a leaf node (primitive value)
paths.push(currentPath);
} else {
paths.push(...subPaths);
}
}
}
return paths;
}
/**
* Flattens an object or array into dot-notation key-value pairs
* @param {*} obj - Object or array to flatten
* @param {string} prefix - Current path prefix
* @returns {Object} Flattened object with dot-notation keys
*/
function flattenObject(obj, prefix = "") {
const flattened = {};
if (obj === null || typeof obj !== "object") {
// Primitive value
if (prefix) {
flattened[prefix] = obj;
}
return flattened;
}
if (Array.isArray(obj)) {
// Handle arrays
for (let i = 0; i < obj.length; i++) {
const currentPath = prefix ? `${prefix}.${i}` : `${i}`;
const subFlattened = flattenObject(obj[i], currentPath);
Object.assign(flattened, subFlattened);
}
} else {
// Handle objects
const keys = Object.keys(obj);
for (const key of keys) {
const currentPath = prefix ? `${prefix}.${key}` : key;
const subFlattened = flattenObject(obj[key], currentPath);
if (Object.keys(subFlattened).length === 0) {
// This is a leaf node (primitive value)
flattened[currentPath] = obj[key];
} else {
Object.assign(flattened, subFlattened);
}
}
}
return flattened;
}
module.exports = { objectToMatrix };