插入数组对象的中间/第一个后更改数组对象的键

问题描述

我正在开发类似Excel的应用程序,但是多维数组存在问题。

我有一系列看起来像这样的列:

var columns = [
  {A: {binding: "A",header: "A"},{B: {binding: "B",header: "B"},{C: {binding: "C",header: "C"}
];

然后我有一个数组,表示每个像这样的单元格的值:

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"}
];

binding数组中对象的columns属性将用于获取每一行的列值。

但是,在一些字母键的中间插入新列时遇到问题。 假设我在列A和列B之间需要一个新列。结果看起来像这样:

var columns = [
  {A: {binding: "A",header: "C"},{D: {binding: "D",header: "D"}
];

它只是将新列推到columns上。

我认为我必须在每一行的所有字母键之间插入一个新的单元格/项目,并重命名所有键(在这种情况下,将键B重命名C,{{1} }到C等。

我希望结果看起来像这样:

D

如果要重命名所有这些键,尤其是当我有120列(A-DZ)和100行时,我会担心性能问题。

我有两个问题:

解决方法

请勿在行或列中使用文字名称。

要提高性能,请将一个数据对象直接链接到列和/或行(在单元格数组中创建_row和_col等属性),并将_cells放入行和列中。

示例:

var data = {};

data.rows = [
{idx: 'A',_cells: []},{idx: 'B',{idx: 'C',_cells: []}
]

data.cols = [
{idx: 'A',_cells: []}
]

data.cells = [];

function addCell( rowIdx,colIdx,value) {
  var row = data.rows[rowIdx];
  var col = data.cols[rowIdx];
  var cell = {value: value,_row: row,_col: col};
  data.cells.push(cell);
  row._cells.push(cell);
  col._cells.push(cell);
}

for(var r=0; r<3; r++)
  for (var c=0;c<3; c++)
    addCell(r,c,'row ' + r + ' col ' + String.fromCharCode(65 + c));

console.log(data);

所以...您可以轻松地插入/删除/排序/重命名行。

您可以轻松地从列中插入/删除/排序/重命名所有单元格。

如果顺序很重要,则可以“映射”按行/列排序的单元格

,

首先,我认为安达姆(Andam)对问题的评论是正确的。当然,有更好的方法可以用一系列对象来制作类似电子表格的显示。我的想法是简单地维护一个包含(至少)列标题和要在列中显示的属性名称的标题对象数组。然后插入一列将只涉及更新该数组(并可能为行默认该属性值。)

但是您仍然希望按照问题所建议的方式进行操作,这是一种可能的实现方式:

// Utility function
const alphaNum = (cs) => (n) => 
  n < cs.length
    ? cs [n % cs.length]
    : alphaNum (cs) (Math.floor(n / cs.length) - 1) + cs [n % cs.length]

// Helper function
const toColumnName = alphaNum ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' .split (''))

// Main function
const insertColumn = (index,data,makeVal) => 
  data .map ((item,i,arr,vals = Object .values (item)) => Object.fromEntries ([
    ...vals .slice (0,index),makeVal (item,...vals .slice (index)
  ] .map ((item,i) => [toColumnName(i),item])))

// Dummy cell creation function
const createCell = (row,rowNbr,colNbr) => 
  `new col inserted at row ${rowNbr} col ${colNbr}`

// Sample data
const 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'}]

// Demo
console .log (insertColumn (1,createCell))
.as-console-wrapper {max-height: 100% !important; top: 0}

  • toColumnName 只需将(从零开始的)索引转换为类似电子表格的列标识符('A''B',{{1 }},... 'C''Z''AA',... 'AB''AZ''BA',... {{ 1}},... 'BB''BZ',...)

  • 它使用 'ZZ' 进行重载,它基于字符数组来表示所使用的伪数字。

  • 'AAA' 是主要功能。它采用插入列的(从零开始)索引,数据和用于创建单元格值的函数。它通过提取值,插入由函数创建的新行,然后从新索引映射回列名,然后使用alphaNum重建对象来更改每一行。

我们在此处传递了一个虚拟的列创建函数,我们可以注意到,该函数传递了行对象,行索引和新列索引。

我不知道它如何在您的真实数据上执行,但是您描述的数字不会让我担心太多。您可以在此处进行一些小的优化。例如,我们不需要重新计算每一行的列名,而可以缓存它们。但是如果性能不能达到您的期望,我只会打扰他们。

再说一次,我认为有更好的方法可以解决潜在的潜在问题。