I am working on an Excel-like application, but I am having problems with a multi-dimensional array.
I have array of columns that looks like this:
var columns = [
{A: {binding: "A",header: "A"},
{B: {binding: "B",header: "B"},
{C: {binding: "C",header: "C"}
];
And then I have an array representing the value of every cell that looks like this:
var data = [
{A:"row 0 col A", B: "row 0 col B", C:"row 0 col C"},
{A:"row 1 col A", B: "row 1 col B", C:"row 1 col C"},
{A:"row 2 col A", B: "row 2 col B", C:"row 2 col C"}
];
The binding
property of the objects in the columns
array will be used to get the column's value for each row.
However, I am encountering an issue when inserting a new column in the middle of some alphabetical keys.
Let's say I need a new column between column A
and column B
. The result looks like this:
var columns = [
{A: {binding: "A",header: "A"},
{B: {binding: "B",header: "B"},
{C: {binding: "C",header: "C"},
{D: {binding: "D",header: "D"}
];
It's just pushing the new column onto columns
.
I think I have to insert a new cell/item between all alphabetical keys for every row, and rename all the keys (in this case, rename keys B
to C
, C
to D
, etc).
I would like the result to look like this:
var data = [
{A:"row 0 col A", B:"new col inserted here", C:"row 0 col B", D:"row 0 col C"},
{A:"row 1 col A", B:"new col inserted here", C:"row 1 col B", D:"row 1 col C"},
{A:"row 2 col A", B:"new col inserted here", C:"row 2 col B", D:"row 2 col C"}
];
I'm concerned about performance issues if I were to rename all these keys, especially if I have 120 columns (A-DZ) and 100 rows.
I have two questions:
- What is the most efficient way to do this?
- Will I have performance issues when renaming these keys if I have lots of rows and columns?
First off, I think the comment to the question from Andam is correct. There are certainly better ways of making a spreadsheet-like display out of an array of objects. My thought would simply to maintain an array of header objects containing (at a minimum) a column title and the name of the property to show in the column. Then inserting a column would simply involve updating that array (and perhaps defaulting that property value for your rows.)
But you still want to proceed in the manner suggested by your question, here's a possible implementation:
toColumnName
simply converts a (zero-based) index into a spreadsheet-like column identifier ('A'
,'B'
,'C'
, ...'Z'
,'AA'
,'AB'
, ...'AZ'
,'BA'
,'BB'
, ...'BZ'
, ...'ZZ'
,'AAA'
, ...)It uses
alphaNum
, which does the heavy-lifting, based on an array of characters to represent the pseudo-digits used.insertColumn
is the main function. It takes the (zero-based) index of the inserted column, the data, and a function used to create your cell value. It changes each row by extracting the values, inserting the new one created by your function, and then mapping back to the column names from the new indices, then rebuilding the object withObject .fromEntries
.Here we pass it a dummy column-creation function, which, we can note, is passed the row object, the row index and the new column index.
I have no idea how it will perform on your realistic data, but the numbers you described wouldn't worry me overmuch. There are some minor optimizations you could do here. For instance, we don't need to recalculate the column names for each row and could cache them instead. But I would only bother with them if the performance doesn't meet your expectations.
And, once again, I think there are better ways to solve the likely underlying problem.