Skip to content

Instantly share code, notes, and snippets.

@alwaisy
Created June 23, 2024 14:28
Show Gist options
  • Save alwaisy/23fd6ebce1b0fdc17a5bd0fe69c2419f to your computer and use it in GitHub Desktop.
Save alwaisy/23fd6ebce1b0fdc17a5bd0fe69c2419f to your computer and use it in GitHub Desktop.
Converts a 2D array of data to an array of objects.
/**
* Converts a key to a specified case.
* @param key - The original key.
* @param keyCase - The case to convert the key to. Can be "camel", "snake", or a custom function.
* @param renameFields - An object that maps original keys to new keys.
* @returns The converted key.
*/
function getKey(
key: string,
keyCase: "camel" | "snake" | ((key: string) => string),
renameFields: Record<string, string>
): string {
// Get the renamed key or use the original key if no rename is specified.
const renamedKey = renameFields[key] || key;
switch (keyCase) {
case "camel":
// Convert the key to camel case.
return toCamelCase(renamedKey);
case "snake":
// Convert the key to snake case.
return toSnakeCase(renamedKey);
default:
// Apply a custom conversion function to the key.
return keyCase(renamedKey);
}
}
/**
* Converts a 2D array of data to an array of objects.
*
* @param data - The 2D array of data, where the first row contains the headers and each subsequent row contains the data.
* @param options - An optional object that can contain the following properties:
* - extraFields: An object containing additional fields to add to each output object.
* - skipFields: An array of field names to skip.
* - keyCase: A function that transforms the field names. Can be 'camel', 'snake', or a custom function.
* - renameFields: An object that maps original field names to new field names.
* @returns An array of objects, where each object represents a row in the input data.
*/
// I need this code to upload the data to appwrite. Notion to csv to 2D array to JS objects array to appwrite.
export function arrayToObjects(
data: string[][],
options: {
extraFields?: Record<string, any>;
skipFields?: string[];
keyCase?: "camel" | "snake" | ((key: string) => string);
renameFields?: Record<string, string>;
} = {}
): Record<string, any>[] {
const {
extraFields = {},
skipFields = [],
keyCase = "camel",
renameFields = {},
} = options;
// Extract the header row
const headers = data[0];
// Create an array to store the objects
const objects: Record<string, any>[] = [];
// Loop through the remaining rows
for (let i = 1; i < data.length; i++) {
// Create an object for the current row
const row = data[i];
const obj: Record<string, any> = {};
// Loop through the headers and assign the corresponding values
for (let j = 0; j < headers.length; j++) {
const header = headers[j];
const value = row[j];
if (value !== "" && !skipFields.includes(header)) {
const key = getKey(header, keyCase, renameFields);
obj[key] = value;
}
}
// Add the extra fields, if provided
for (const [key, value] of Object.entries(extraFields)) {
obj[key] = value;
}
// Only add the object to the array if it has at least one non-empty value
if (Object.keys(obj).length > 0) {
objects.push(obj);
}
}
return objects;
}
// lodash or underscore js better serves the purpose
function toCamelCase(str: string): string {
return str
.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) =>
index === 0 ? word.toLowerCase() : word.toUpperCase()
)
.replace(/\s+/g, "");
}
function toSnakeCase(str: string): string {
return str
.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) =>
index === 0 ? word.toLowerCase() : "_" + word.toLowerCase()
)
.replace(/\s+/g, "");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment