Write a function that converts an array of objectsarr into a matrixm.
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 rowm[0] 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 lexicographically ascending order.
Input & Output
Example 1 — Basic Nested Objects
$Input:arr = [{"b": 1, "a": 2}, {"b": 3, "c": 4}]
›Output:[["a","b","c"],["2","1",""],["""3","4"]]
💡 Note:Keys are "a", "b", "c" in lexicographical order. First object has values for "a" and "b", second object has values for "b" and "c".
The key insight is to flatten nested objects into dot-notation paths, collect all unique column names, sort them lexicographically, and build a matrix. The optimal approach processes each object once to flatten and collect columns, then constructs the final matrix. Time: O(n × k + k log k), Space: O(n × k) where n is number of objects and k is average number of keys per object.
Common Approaches
✓
Multiple Pass Approach
⏱️ Time: O(n × k × d)
Space: O(n × k)
First pass through all objects to collect unique column names, second pass to flatten each object, third pass to build the matrix with proper ordering.
Single Pass with Dynamic Building
⏱️ Time: O(n × k + k log k)
Space: O(n × k)
Process each object once, flattening and collecting columns dynamically. Build the final matrix by reorganizing data after all columns are known.
Multiple Pass Approach — Algorithm Steps
Step 1: Scan all objects to find unique keys/paths
Step 2: Sort column names lexicographically
Step 3: For each object, flatten and map to columns
Step 4: Build matrix row by row
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Pass 1: Collect Keys
Scan all objects to find unique column names
2
Pass 2: Sort & Flatten
Sort columns lexicographically and flatten objects
3
Pass 3: Build Matrix
Create matrix with headers and data rows
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum {
JSON_NULL,
JSON_BOOL,
JSON_NUMBER,
JSON_STRING,
JSON_ARRAY,
JSON_OBJECT
} json_type_t;
typedef struct json_value {
json_type_t type;
union {
int bool_val;
double number_val;
char* string_val;
struct {
struct json_value* items;
int count;
} array_val;
struct {
char** keys;
struct json_value* values;
int count;
} object_val;
};
} json_value_t;
typedef struct {
char* key;
json_value_t value;
} flat_entry_t;
typedef struct {
flat_entry_t* entries;
int count;
int capacity;
} flat_map_t;
json_value_t parse_json(const char* json);
void flatten_object(json_value_t* obj, const char* prefix, flat_map_t* result);
int compare_strings(const void* a, const void* b);
char* json_to_string(json_value_t* val);
void free_json_value(json_value_t* val);
void free_flat_map(flat_map_t* map);
char* skip_whitespace(char* str) {
while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r') str++;
return str;
}
char* parse_string(char* json, char** result) {
json++; // skip opening quote
char* start = json;
while (*json && *json != '"') {
if (*json == '\\') json++; // skip escaped character
json++;
}
int len = json - start;
*result = malloc(len + 1);
strncpy(*result, start, len);
(*result)[len] = '\0';
return json + 1; // skip closing quote
}
char* parse_number(char* json, double* result) {
char* end;
*result = strtod(json, &end);
return end;
}
json_value_t parse_json_simple(char* json) {
json_value_t result = {0};
json = skip_whitespace(json);
if (*json == '{') {
result.type = JSON_OBJECT;
result.object_val.count = 0;
result.object_val.keys = malloc(100 * sizeof(char*));
result.object_val.values = malloc(100 * sizeof(json_value_t));
json++; // skip {
json = skip_whitespace(json);
while (*json && *json != '}') {
if (result.object_val.count > 0) {
json++; // skip comma
json = skip_whitespace(json);
}
// Parse key
char* key;
json = parse_string(json, &key);
json = skip_whitespace(json);
json++; // skip colon
json = skip_whitespace(json);
// Parse value - simplified for basic types
json_value_t val = {0};
if (*json == '"') {
val.type = JSON_STRING;
json = parse_string(json, &val.string_val);
} else if (strncmp(json, "null", 4) == 0) {
val.type = JSON_NULL;
json += 4;
} else if (strncmp(json, "true", 4) == 0) {
val.type = JSON_BOOL;
val.bool_val = 1;
json += 4;
} else if (strncmp(json, "false", 5) == 0) {
val.type = JSON_BOOL;
val.bool_val = 0;
json += 5;
} else if (*json == '{') {
// Nested object - simplified parsing
int depth = 0;
char* start = json;
do {
if (*json == '{') depth++;
else if (*json == '}') depth--;
json++;
} while (depth > 0 && *json);
int len = json - start;
char* nested_json = malloc(len + 1);
strncpy(nested_json, start, len);
nested_json[len] = '\0';
val = parse_json_simple(nested_json);
free(nested_json);
} else {
val.type = JSON_NUMBER;
json = parse_number(json, &val.number_val);
}
result.object_val.keys[result.object_val.count] = key;
result.object_val.values[result.object_val.count] = val;
result.object_val.count++;
json = skip_whitespace(json);
}
} else if (*json == '[') {
result.type = JSON_ARRAY;
result.array_val.count = 0;
result.array_val.items = malloc(100 * sizeof(json_value_t));
json++; // skip [
json = skip_whitespace(json);
while (*json && *json != ']') {
if (result.array_val.count > 0) {
json++; // skip comma
json = skip_whitespace(json);
}
// Parse array item - simplified
if (*json == '{') {
int depth = 0;
char* start = json;
do {
if (*json == '{') depth++;
else if (*json == '}') depth--;
json++;
} while (depth > 0 && *json);
int len = json - start;
char* item_json = malloc(len + 1);
strncpy(item_json, start, len);
item_json[len] = '\0';
result.array_val.items[result.array_val.count] = parse_json_simple(item_json);
free(item_json);
}
result.array_val.count++;
json = skip_whitespace(json);
}
}
return result;
}
void flatten_object(json_value_t* obj, const char* prefix, flat_map_t* result) {
if (obj->type == JSON_OBJECT) {
for (int i = 0; i < obj->object_val.count; i++) {
char new_key[1000];
if (strlen(prefix) == 0) {
strcpy(new_key, obj->object_val.keys[i]);
} else {
sprintf(new_key, "%s.%s", prefix, obj->object_val.keys[i]);
}
json_value_t* val = &obj->object_val.values[i];
if (val->type == JSON_OBJECT || val->type == JSON_ARRAY) {
flatten_object(val, new_key, result);
} else {
if (result->count >= result->capacity) {
result->capacity *= 2;
result->entries = realloc(result->entries, result->capacity * sizeof(flat_entry_t));
}
result->entries[result->count].key = malloc(strlen(new_key) + 1);
strcpy(result->entries[result->count].key, new_key);
result->entries[result->count].value = *val;
result->count++;
}
}
}
}
int compare_strings(const void* a, const void* b) {
return strcmp(*(const char**)a, *(const char**)b);
}
char* json_to_string(json_value_t* val) {
char* result = malloc(100);
switch (val->type) {
case JSON_NULL:
strcpy(result, "null");
break;
case JSON_BOOL:
strcpy(result, val->bool_val ? "true" : "false");
break;
case JSON_NUMBER:
if (val->number_val == (int)val->number_val) {
sprintf(result, "%d", (int)val->number_val);
} else {
sprintf(result, "%.6g", val->number_val);
}
break;
case JSON_STRING:
strcpy(result, val->string_val);
break;
default:
strcpy(result, "");
break;
}
return result;
}
int main() {
char buffer[10000];
fgets(buffer, sizeof(buffer), stdin);
buffer[strcspn(buffer, "\n")] = 0;
json_value_t json = parse_json_simple(buffer);
if (json.type != JSON_ARRAY || json.array_val.count == 0) {
printf("[]");
return 0;
}
// Collect all columns
char** all_columns = malloc(1000 * sizeof(char*));
int column_count = 0;
flat_map_t* flat_objects = malloc(json.array_val.count * sizeof(flat_map_t));
for (int i = 0; i < json.array_val.count; i++) {
flat_objects[i].entries = malloc(100 * sizeof(flat_entry_t));
flat_objects[i].count = 0;
flat_objects[i].capacity = 100;
flatten_object(&json.array_val.items[i], "", &flat_objects[i]);
for (int j = 0; j < flat_objects[i].count; j++) {
char* key = flat_objects[i].entries[j].key;
int found = 0;
for (int k = 0; k < column_count; k++) {
if (strcmp(all_columns[k], key) == 0) {
found = 1;
break;
}
}
if (!found) {
all_columns[column_count] = malloc(strlen(key) + 1);
strcpy(all_columns[column_count], key);
column_count++;
}
}
}
qsort(all_columns, column_count, sizeof(char*), compare_strings);
// Print result
printf("[");
// Header row
printf("[");
for (int i = 0; i < column_count; i++) {
if (i > 0) printf(",");
printf("\"%s\"", all_columns[i]);
}
printf("]");
// Data rows
for (int i = 0; i < json.array_val.count; i++) {
printf(",[");
for (int j = 0; j < column_count; j++) {
if (j > 0) printf(",");
char* value = "";
for (int k = 0; k < flat_objects[i].count; k++) {
if (strcmp(flat_objects[i].entries[k].key, all_columns[j]) == 0) {
value = json_to_string(&flat_objects[i].entries[k].value);
break;
}
}
printf("\"%s\"", value);
}
printf("]");
}
printf("]\n");
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
O(n × k × d)
n objects, k keys per object, d depth for flattening, multiple passes
n
2n
✓ Linear Growth
Space Complexity
O(n × k)
Store all flattened objects and final matrix
n
2n
⚡ Linearithmic Space
32.4K Views
MediumFrequency
~35 minAvg. Time
856 Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.