From 6156ba8bc5481e6ae916bc1aebea0651c257dff8 Mon Sep 17 00:00:00 2001 From: Priyansh Date: Sat, 22 Jan 2022 21:33:06 -0500 Subject: feat: function to load data from json and flattenJSON --- src/lib/data.ts | 42 +++++++++++++++++++++ src/lib/display.ts | 6 +-- src/lib/frame.ts | 18 +++++---- src/lib/info.ts | 107 +++++++++++++++++++++++++++++------------------------ 4 files changed, 114 insertions(+), 59 deletions(-) (limited to 'src/lib') diff --git a/src/lib/data.ts b/src/lib/data.ts index dcc948b..9649d6d 100644 --- a/src/lib/data.ts +++ b/src/lib/data.ts @@ -1,3 +1,6 @@ +import { Frame } from '../index'; +import { isValidJSONObject } from '../helpers/arrayFunctions'; + /** * flattenArray - flattens a 2D into a single array * @param array: the array to be flattened @@ -14,3 +17,42 @@ export function flatten(array: any[][]): any[] { } return flattenedArray; } + +/** + * fromJSON - converts a JSON string into a rowdata - framedata is a 2D array + * @param json: the JSON string to be converted + * @returns the rowdata + */ +export function fromJSON(this: Frame, json: any): Frame { + if (isValidJSONObject(json)) { + const header: string[] = []; + const rowdata: any[][] = []; + // loop through each row + for (let i = 0; i < json.length; i++) { + // get all the keys and store them in the header + for (const key in json[i]) { + if (!header.includes(key)) { + header.push(key); + } + } + } + // loop through each row + for (let i = 0; i < json.length; i++) { + // get the values of the keys present in the header, if the values are not present in the row, add null + const row: any[] = []; + for (let j = 0; j < header.length; j++) { + if (json[i][header[j]] !== undefined) { + row.push(json[i][header[j]]); + } else { + row.push(null); + } + } + rowdata.push(row); + } + this.rowdata = rowdata; + this.columns = header; + return this; + } else { + throw new Error('Invalid JSON'); + } +} diff --git a/src/lib/display.ts b/src/lib/display.ts index 6aeb029..c33df70 100644 --- a/src/lib/display.ts +++ b/src/lib/display.ts @@ -40,7 +40,7 @@ function getTable( * @throws Error if the frame is empty */ export function show(this: Frame): void { - if (!this.rowdata.length) { + if (this.rowdata.length === 0) { throw new Error('Set data before printing'); } const numberOfRows = this.rowdata.length; @@ -74,7 +74,7 @@ export function show(this: Frame): void { * @throws Error if the frame is empty */ export function head(this: Frame, n = 5): void { - if (!this.rowdata.length) { + if (this.rowdata.length === 0) { throw new Error('Set data before printing'); } // Check if n is greater than the number of rows @@ -95,7 +95,7 @@ export function head(this: Frame, n = 5): void { * @throws Error if the frame is empty */ export function tail(this: Frame, n = 5): void { - if (!this.rowdata.length) { + if (this.rowdata.length === 0) { throw new Error('Set data before printing'); } // Check if n is greater than the number of rows diff --git a/src/lib/frame.ts b/src/lib/frame.ts index 8ed1316..d257fb4 100644 --- a/src/lib/frame.ts +++ b/src/lib/frame.ts @@ -63,12 +63,16 @@ export function setHeader(rowdata: any[][], header: any[]): Array { */ export function generateHeader(rd: Array): Array { - const maxSizedArrayLength = rd.reduce((acc, curr) => { - return acc.length > curr.length ? acc : curr; - }).length; - const header: Array = []; - for (let i = 0; i < maxSizedArrayLength; i++) { - header.push(`Column ${i + 1}`); + if (rd?.length) { + const maxSizedArrayLength = rd.reduce((acc, curr) => { + return acc.length > curr.length ? acc : curr; + }).length; + const header: Array = []; + for (let i = 0; i < maxSizedArrayLength; i++) { + header.push(`Column ${i + 1}`); + } + return header; + } else { + return []; } - return header; } diff --git a/src/lib/info.ts b/src/lib/info.ts index 814992b..9338c75 100644 --- a/src/lib/info.ts +++ b/src/lib/info.ts @@ -17,58 +17,67 @@ export function getSize(rowdata: any[]): number { * @returns the type of data present in each column of the frame */ export function info(this: Frame): void { - const info: Array = []; - info.push(['#', 'Column Name', 'Types', 'Empty Values']); - let counter = 0; - const countDataTypes = {} as any; - this.columns.forEach((column: string, index: number) => { - // get all the types of data in the column, do not repeat the same type - let nullValuesPresentInRow = false; - const columnDataTypes = this.rowdata.map((row: any[]) => { + if (this.rowdata.length === 0) { + throw new Error('Frame is empty'); + } else { + const info: Array = []; + info.push(['#', 'Column Name', 'Types', 'Empty Values']); + let counter = 0; + const countDataTypes = {} as any; + this.columns.forEach((column: string, index: number) => { + // get all the types of data in the column, do not repeat the same type + let nullValuesPresentInRow = false; + const columnDataTypes = this.rowdata.map((row: any[]) => { + if ( + row[index] === null || + row[index] === undefined || + row[index] === '' + ) { + nullValuesPresentInRow = true; + } + const currentType = String(typeof row[index]); + if (!Object.keys(countDataTypes).includes(currentType)) { + Object.assign(countDataTypes, { [currentType]: 1 }); + } else { + const getKeyValue = (obj: T, key: K): T[K] => + obj[key]; + const currentValue = getKeyValue(countDataTypes, currentType); + Object.assign(countDataTypes, { [currentType]: currentValue + 1 }); + } + return typeof row[index]; + }); + const uniqueDataTypes = [...new Set(columnDataTypes)]; + info.push([ + counter, + column, + [...uniqueDataTypes], + nullValuesPresentInRow + ]); + counter++; + }); + let dataTypesString = ''; + // Iterate through the countDataTypes object and create a string of the data types + Object.keys(countDataTypes).forEach((key: string) => { + dataTypesString += `${key}(${countDataTypes[key]})`; + // check if the key is not the last key in the object if ( - row[index] === null || - row[index] === undefined || - row[index] === '' + Object.keys(countDataTypes).indexOf(key) !== + Object.keys(countDataTypes).length - 1 ) { - nullValuesPresentInRow = true; - } - const currentType = String(typeof row[index]); - if (!Object.keys(countDataTypes).includes(currentType)) { - Object.assign(countDataTypes, { [currentType]: 1 }); - } else { - const getKeyValue = (obj: T, key: K): T[K] => - obj[key]; - const currentValue = getKeyValue(countDataTypes, currentType); - Object.assign(countDataTypes, { [currentType]: currentValue + 1 }); + dataTypesString += ', '; } - return typeof row[index]; }); - const uniqueDataTypes = [...new Set(columnDataTypes)]; - info.push([counter, column, [...uniqueDataTypes], nullValuesPresentInRow]); - counter++; - }); - let dataTypesString = ''; - // Iterate through the countDataTypes object and create a string of the data types - Object.keys(countDataTypes).forEach((key: string) => { - dataTypesString += `${key}(${countDataTypes[key]})`; - // check if the key is not the last key in the object - if ( - Object.keys(countDataTypes).indexOf(key) !== - Object.keys(countDataTypes).length - 1 - ) { - dataTypesString += ', '; - } - }); - console.log(`RangeIndex: ${this.size} elements, 0 to ${this.size - 1}`); - console.log( - `Shape: ${this.shape.split(' x ')[0].trim()} rows, ${this.shape - .split(' x ')[1] - .trim()} columns` - ); - console.log(table(info)); - // Remove the previous printed newline - process.stdout.write('\x1B[1A\x1B[2K'); - console.log(`Data Types: ${dataTypesString}`); - console.log(`Memory Usage: ${sizeof(this)} bytes`); + console.log(`RangeIndex: ${this.size} elements, 0 to ${this.size - 1}`); + console.log( + `Shape: ${this.shape.split(' x ')[0].trim()} rows, ${this.shape + .split(' x ')[1] + .trim()} columns` + ); + console.log(table(info)); + // Remove the previous printed newline + process.stdout.write('\x1B[1A\x1B[2K'); + console.log(`Data Types: ${dataTypesString}`); + console.log(`Memory Usage: ${sizeof(this)} bytes`); + } } -- cgit v1.2.3