Skip to content

Commit

Permalink
added support for transpose()
Browse files Browse the repository at this point in the history
  • Loading branch information
NB10328 authored and NB10328 committed Oct 6, 2021
1 parent c81b81d commit a51d62a
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 12 deletions.
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1315,6 +1315,55 @@ console.log(table.toString());
| 3 | Jim | 83 |
+---+------+----+
```
### Transposing
#### instance.transpose()
Transposes table by exchanging rows for columns.
Example:
```javascript
const table =
new AsciiTable3('Sample table')
.setHeading('Name', 'Age', 'Eye color')
.addRowMatrix([
['John', 23, 'green'],
['Mary', 16, 'brown'],
['Rita', 47, 'blue'],
['Peter', 8, 'brown']
]);

console.log(table.toString());
```
```
+-------------------------+
| Sample table |
+-------+-----+-----------+
| Name | Age | Eye color |
+-------+-----+-----------+
| John | 23 | green |
| Mary | 16 | brown |
| Rita | 47 | blue |
| Peter | 8 | brown |
+-------+-----+-----------+
```
```javascript
// transpose table
table.transpose();

console.log(table.toString());
```
```
+------------------------------------------+
| Sample table |
+-----------+-------+-------+------+-------+
| Name | John | Mary | Rita | Peter |
| Age | 23 | 16 | 47 | 8 |
| Eye color | green | brown | blue | brown |
+-----------+-------+-------+------+-------+
```
### Serialization
Expand Down
63 changes: 61 additions & 2 deletions ascii-table3.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,10 @@ class AsciiTable3 {
* @static
* @param {number} len Length of array.
* @param {*} [value] The fill value (optional).
* @returns {*[]} Array filled with with desired value.
*/
static arrayFill(len, value) {
var result = [];
const result = [];

for (var i = 0; i < len; i++) {
result.push(value);
Expand Down Expand Up @@ -546,13 +547,33 @@ class AsciiTable3 {
}

/**
* Table rows getter
* Table rows getter.
* @returns {*[]} Array with row cell values (column array).
*/
getRows() {
return Array.from(this.rows);
}

/**
* Sets cell value for this row and column combination.
* @param {number} row Desired row number (1-based index).
* @param {number} col Desired column number (1-based index).
* @param {*} value The cell value to set.
*/
setCell(row, col, value) {
this.rows[row - 1][col - 1] = value;
}

/**
* Gets cell value for this row and column combination.
* @param {number} row Desired row number (1-based index).
* @param {number} col Desired column number (1-based index).
* @returns {*} The cell value.
*/
getCell(row, col) {
return this.getRows()[row - 1][col - 1];
}

/**
* Sets the preset width for a given column rendering output.
* @param {number} idx Column index to align (starts at 1).
Expand Down Expand Up @@ -814,6 +835,44 @@ class AsciiTable3 {
return this.justify ? this.justify : false;
}

/**
* Transposes table by exchanging rows for columns.
* @returns {AsciiTable3} The AsciiTable3 object instance.
*/
transpose() {
// get number of data columns
const nCols = this.getHeading().length > 0 ? this.getHeading().length : this.getRows()[0].length;

// get number of data rows
const nRows = this.getRows().length;

// create new matrix with number of rows equal number of columns
const newMatrix = AsciiTable3.arrayFill(nCols);

// columns where data starts (depends on heading existence)
const dataStartCol = this.getHeading().length > 0 ? 1 : 0;

// loop over rows
for (var row = 0; row < newMatrix.length; row++) {
// column array for this row (number of rows + heading if needed)
newMatrix[row] = AsciiTable3.arrayFill(nRows + dataStartCol);

if (this.getHeading()) {
// setup first column with heading values
newMatrix[row][0] = this.getHeading()[row];
}

// loop over columns
for (var col = dataStartCol; col < newMatrix[0].length; col++) {
// fill row with column data values
newMatrix[row][col] = this.getCell(col + Math.abs(dataStartCol - 1), row + 1);
}
}

// new value
return new AsciiTable3(this.getTitle()).addRowMatrix(newMatrix);
}

/**
* Return the JSON representation of the table, this also allows us to call JSON.stringify on the instance.
* @returns {string} The table JSON representation.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ascii-table3",
"version": "0.5.4",
"version": "0.6.0",
"author": "João Simões <[email protected]> (https://github.com/AllMightySauron)",
"description": "Javascript ASCII renderer for beautiful console-based tables",
"repository": {
Expand Down
18 changes: 10 additions & 8 deletions samples.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ const table =

console.log(`base table:\n${table.toString()}`);

// Example 2. cell margins
// example 2. transpose
console.log(`transpose table:\n${table.transpose().toString()}`);

// Example 3. cell margins
console.log ('>>>>>> example 2: cell margins');

table.setCellMargin(0);
Expand All @@ -28,7 +31,7 @@ console.log(`cell margin = 0:\n${table.toString()}`);
table.setCellMargin(2);
console.log(`cell margin = 2:\n${table.toString()}`);

// example 3. Test out styles
// example 4. Test out styles
console.log ('>>>>>> example 3: test out styles');

table.setCellMargin(1);
Expand All @@ -39,7 +42,7 @@ table.getStyles().forEach(style => {
console.log(`${style.name}:\n${table.toString()}`);
});

// example 4. column width
// example 5. column width
console.log ('>>>>>> example 4: column width');

table.setStyle("ramac");
Expand All @@ -52,7 +55,7 @@ console.log(`name width = 6:\n${table.toString()}`);
table.setWidths([10, 8, 12]);
console.log(`multiple widths = [10, 8, 12]:\n${table.toString()}`);

// example 5. adding a new style
// example 6. adding a new style
console.log ('>>>>>> example 5: adding a new style');

const roundedStyle = {
Expand All @@ -77,27 +80,26 @@ table.addStyle(roundedStyle);
table.setStyle("rounded");
console.log(`rounded style:\n${table.toString()}`);

// example 6. row data wrapping
// example 7. row data wrapping
console.log ('>>>>>> example 6: row data wrapping');
table.clearRows();
table.addRow('James Bond', 41, 'blue').addRow('Harry Potter', 18, 'brown').addRow('Scooby Doo', 23, 'brown').addRow('Mickey Mouse', 120, 'black');
table.setWidth(1, 8).setWrapped(1);

console.log(`data wrapping:\n${table.toString()}`);

// example 7. justification (all columns of same width)
// example 8. justification (all columns of same width)
console.log ('>>>>>> example 7: justification (all columns of same width)');
table.setWidths().setWrapped(1, false);
table.setJustify();

console.log(`justified:\n${table.toString()}`);

// example 8. no title or heading
// example 9. no title or heading
console.log ('>>>>>> example 8: no title or heading');
table.setJustify(false);
table.setTitle();
table.setHeading();

table.setStyle('ramac');
console.log(`no title/heading:\n${table.toString()}`);

113 changes: 112 additions & 1 deletion test/ascii-table3.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ describe('Heading', () => {
});
});

describe('DataRows', () => {
describe('Data rows', () => {
it ('addRow/getRows', () => {
const aTable = new AsciiTable3('Dummy title')
.setHeading('Title', 'Count', 'Rate (%)')
Expand Down Expand Up @@ -193,6 +193,37 @@ describe('DataRows', () => {
});
});

describe('Cell values', () => {
it ('getCell', () => {
const aTable = new AsciiTable3('People')
.setHeading('Name', 'Age', 'Eye color')
.addRowMatrix([
['John', 18, 'green'],
['Peter', 5, 'brown'],
['Mary', 40, 'blue'],
['Timothy', 16, 'hazel'],
]);

assert.strictEqual(aTable.getCell(1, 1), 'John');
assert.strictEqual(aTable.getCell(3, 2), 40);
});

it ('setCell', () => {
const aTable = new AsciiTable3('People')
.setHeading('Name', 'Age', 'Eye color')
.addRowMatrix([
['John', 18, 'green'],
['Peter', 5, 'brown'],
['Mary', 40, 'blue'],
['Timothy', 16, 'hazel'],
]);

assert.strictEqual(aTable.getCell(3, 2), 40);
aTable.setCell(3, 2, 55);
assert.strictEqual(aTable.getCell(3, 2), 55);
});
});

describe('Sorting', () => {
it ('sort', () => {
const aTable =
Expand Down Expand Up @@ -819,3 +850,83 @@ describe('Clearing data', () => {
assert.strictEqual(aTable.isJustify(), false);
});
});

describe('Transpose', () => {
it ('no heading', () => {
const aTable = new AsciiTable3('People')
.addRowMatrix([
['John', 18, 'green'],
['Peter', 5, 'brown'],
['Mary', 40, 'blue'],
['Timothy', 16, 'hazel'],
]);

const newTable = aTable.transpose();

// same title
assert.strictEqual(newTable.getTitle(), aTable.getTitle());

// number of rows / columns
assert.strictEqual(newTable.getRows().length, aTable.getRows()[0].length);
assert.strictEqual(newTable.getRows()[0].length, aTable.getRows().length);

// test cell values
for (var row = 0; row < newTable.getRows().length; row++) {
for (var col = 0; col < newTable.getRows()[0].length; col++) {
assert.strictEqual(newTable.getCell(row + 1, col + 1), aTable.getCell(col + 1, row + 1));
}
}
});

it ('heading', () => {
const aTable = new AsciiTable3('People')
.setHeading('Name', 'Age', 'Eye color')
.addRowMatrix([
['John', 18, 'green'],
['Peter', 5, 'brown'],
['Mary', 40, 'blue'],
['Timothy', 16, 'hazel'],
]);

const newTable = aTable.transpose();

// same title
assert.strictEqual(newTable.getTitle(), aTable.getTitle());

// number of rows / columns
assert.strictEqual(newTable.getRows().length, aTable.getRows()[0].length);
assert.strictEqual(newTable.getRows()[0].length, aTable.getRows().length + 1); // extra column on new table for heading

// test original heading exists on first column of transposed matrix
for (var row = 0; row < newTable.getRows().length; row++) {
assert.strictEqual(newTable.getRows()[row][0], aTable.getHeading()[row]);
}

// test cell values
for (row = 0; row < newTable.getRows().length; row++) {
for (var col = 1; col < newTable.getRows()[0].length; col++) {
assert.strictEqual(newTable.getCell(row + 1, col + 1), aTable.getCell(col, row + 1));
}
}
});

it ('heading (no data)', () => {
const aTable = new AsciiTable3('People')
.setHeading('Name', 'Age', 'Eye color');

const newTable = aTable.transpose();

// same title
assert.strictEqual(newTable.getTitle(), aTable.getTitle());

// number of rows / columns
assert.strictEqual(newTable.getRows().length, aTable.getHeading().length);
assert.strictEqual(newTable.getRows()[0].length, 1); // 1 column for heading

// test original heading exists on first column of transposed matrix
for (var row = 0; row < newTable.getRows().length; row++) {
assert.strictEqual(newTable.getRows()[row][0], aTable.getHeading()[row]);
}
});

});

0 comments on commit a51d62a

Please sign in to comment.