百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

稀疏数组——前端电子表格中的应用实战

wptr33 2025-06-04 02:10 21 浏览

前文中我们详细介绍过稀疏数组的那些事儿,以及在实际项目中,稀疏数组如何在前端电子表格中发挥出它最大的效果。而这次,我们将从实战应用出发,为大家介绍稀疏数组在前端中的具体应用。

我们都知道在Javascript中是通过Array()构造函数构件稀疏矩阵,或者通过数组,设定数组的索引长度大于当前数组长度的方式来创建稀疏矩阵。

var arr = new Array(100)   //arr没有元素,但arr.length是100
var a = [];  //创建一个空数组,length为0
a[50] = 50;  //赋值添加一个元素,length为 51

稀疏数组中,没有元素的结点为empty,获取这些结点将返回结果undefined。通过使用index in array可以判断一个结点是否有元素。例如下面代码中,a[0]和a[1]的返回都为undefined,但是a[1]其实为空。

JS中已经支持稀疏数组的存储,但在实际情况中,我们保存稀疏数组的保存并不是直接进行,而是会根据实际情况构建其他存储方式保存稀疏数组。想了解为什么要“多此一举”,这里就需要大家了解一个概念——数据持久化。

我们在前端进行许多操作时,会产生许多数据,例如在前端表格进行多人填报、协同的时候,会出现很多需要长期保存的数据,有些数据还要转移到其它位置中便于人们存储、管理、操作等。而实现这一目标的关键点就是数据的持久化,我们需要将内存中数据序列化为json等存储格式保存到数据库并还能反序列化到内存。在之前的文章详解电子表格中的json数据:序列化与反序列化已经具体介绍了,大家有兴趣可以查看。

看到这里,你以为问题彻底解决了吗,图样图森破。

为了解决数据持久化,我们使用了JSON,但这时新的问题也随之出现,JSON存储中没有undefined。我们对数组进行操作的时候,数组中empty字段都会序列化为null,如下图所示。

JSON.stringify(a)
'[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,50]'

再次parse后,数组便不再是稀疏数组了。

JSON.parse(JSON.stringify(a))
(51) [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 50]

这种情况下,为了解决JSON数据在转化过程中上述出现的情况,我们就需要构建一些其他存储方式,来更好地解决这个问题~而这些存储方式又有哪些特点,让我们一起看看。

1、对象存储

在前端利用JS的语言特点,我们可以通过Object可以轻松实现Sparse Array。例如在Spread JS中,对象属性名称对应所在单元格的行列,value属性保存单元格的值,同样可以拓展出formula和style等属性保存单元格公式和样式。使用Sparse Array不用初始化大小也不用关心数据的扩容,需要做行列操作时也只需要改变行列属性的引用即可。

上图中的数据存储结果如下

{
    "0": {
        "0": {
            "value": 0
        }
    },
    "2": {
        "1": {
            "value": 2
        },
        "3": {
            "value": "S"
        }
    },
    "4": {
        "3": {
            "value": 3
        }
    }
}

需要存取数据时候直接通过对象属性访问。下面是JS Sparse Array的一个简单对象实现。

function SparseArray(){
    this._array = {}
}
SparseArray.prototype.setValue = function(row, col, data){
    if(!this._array[row]){
        this._array[row] = {}
    }
    this._array[row][col] = data
}
SparseArray.prototype.getValue = function(row, col){
    if(this._array[row]){
        return this._array[row][col]
    }
    return undefined;
}
let arr = new SparseArray();
arr.setValue(3, 3, 5);
console.log(arr.getValue(3, 3))    // 5
 
 
 

2、三元组

在矩阵中每一个元素有行标,列标,元素值三个信息,将元素按需放入数组中便是三元组存储。存储结构可以是一个包含元素信息对象,也可以直接简化为一个长度为3的数组。三元组的存储方式可以方便记录类似下图的轨迹信息或者自由曲线信息,通过对数组进行push和pop,可以方便进行回退和前进。

上图中的轨迹信息,以数组三元组存储后如下,元素value代表当前已元素数量,也可以使用对象记录时间等更多信息。

[
    [1,1,1],
    [5,8,2],
    [4,3,3],
    [1,5,4]
]

下面,我们就用这种方式建立一个undoStack记录回退。

function TSMatrix(){
this._array = [];
this.undoStack = []
}
 
TSMatrix.prototype.addNode = function(row, col, value){
this._array.push([row, col, value])
}
TSMatrix.prototype.canUndo = function(){
return this._array.length > 0;
}
TSMatrix.prototype.undo = function(){
if(this._array.length > 0){
this.undoStack.push(this._array.pop())
}
}
TSMatrix.prototype.canRedo = function(){
return this.undoStack.length > 0;
}
TSMatrix.prototype.redo = function(){
if(this._array.length > 0){
this._array.push(this.undoStack.pop())
}
}
TSMatrix.prototype.print = function(){
console.log(JSON.stringify(this._array))
}
let mat = new TSMatrix();
mat.addNode(1, 1, 1)
mat.addNode(5, 8, 2)
mat.addNode(4, 3, 3)
mat.addNode(1, 5, 4)
mat.print() //[[1,1,1],[5,8,2],[4,3,3],[1,5,4]]
mat.undo()
mat.print()  //[[1,1,1],[5,8,2],[4,3,3]]
mat.redo()
mat.print()  //[[1,1,1],[5,8,2],[4,3,3],[1,5,4]]

除了以上两种方式,还可以将上述方式结合,建立十字链表以应对更复杂的场景。大家如果感兴趣点个赞我们下次继续说。

在后续的内容中,我们还会继续为大家带来其他前端电子表格技术中的深度解密,走过路过不要错过。

相关推荐

MySQL进阶五之自动读写分离mysql-proxy

自动读写分离目前,大量现网用户的业务场景中存在读多写少、业务负载无法预测等情况,在有大量读请求的应用场景下,单个实例可能无法承受读取压力,甚至会对业务产生影响。为了实现读取能力的弹性扩展,分担数据库压...

Postgres vs MySQL_vs2022连接mysql数据库

...

3分钟短文 | Laravel SQL筛选两个日期之间的记录,怎么写?

引言今天说一个细分的需求,在模型中,或者使用laravel提供的EloquentORM功能,构造查询语句时,返回位于两个指定的日期之间的条目。应该怎么写?本文通过几个例子,为大家梳理一下。学习时...

一文由浅入深带你完全掌握MySQL的锁机制原理与应用

本文将跟大家聊聊InnoDB的锁。本文比较长,包括一条SQL是如何加锁的,一些加锁规则、如何分析和解决死锁问题等内容,建议耐心读完,肯定对大家有帮助的。为什么需要加锁呢?...

验证Mysql中联合索引的最左匹配原则

后端面试中一定是必问mysql的,在以往的面试中好几个面试官都反馈我Mysql基础不行,今天来着重复习一下自己的弱点知识。在Mysql调优中索引优化又是非常重要的方法,不管公司的大小只要后端项目中用到...

MySQL索引解析(联合索引/最左前缀/覆盖索引/索引下推)

目录1.索引基础...

你会看 MySQL 的执行计划(EXPLAIN)吗?

SQL执行太慢怎么办?我们通常会使用EXPLAIN命令来查看SQL的执行计划,然后根据执行计划找出问题所在并进行优化。用法简介...

MySQL 从入门到精通(四)之索引结构

索引概述索引(index),是帮助MySQL高效获取数据的数据结构(有序),在数据之外,数据库系统还维护者满足特定查询算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构...

mysql总结——面试中最常问到的知识点

mysql作为开源数据库中的榜一大哥,一直是面试官们考察的重中之重。今天,我们来总结一下mysql的知识点,供大家复习参照,看完这些知识点,再加上一些边角细节,基本上能够应付大多mysql相关面试了(...

mysql总结——面试中最常问到的知识点(2)

首先我们回顾一下上篇内容,主要复习了索引,事务,锁,以及SQL优化的工具。本篇文章接着写后面的内容。性能优化索引优化,SQL中索引的相关优化主要有以下几个方面:最好是全匹配。如果是联合索引的话,遵循最...

MySQL基础全知全解!超详细无废话!轻松上手~

本期内容提醒:全篇2300+字,篇幅较长,可搭配饭菜一同“食”用,全篇无废话(除了这句),干货满满,可收藏供后期反复观看。注:MySQL中语法不区分大小写,本篇中...

深入剖析 MySQL 中的锁机制原理_mysql 锁详解

在互联网软件开发领域,MySQL作为一款广泛应用的关系型数据库管理系统,其锁机制在保障数据一致性和实现并发控制方面扮演着举足轻重的角色。对于互联网软件开发人员而言,深入理解MySQL的锁机制原理...

Java 与 MySQL 性能优化:MySQL分区表设计与性能优化全解析

引言在数据库管理领域,随着数据量的不断增长,如何高效地管理和操作数据成为了一个关键问题。MySQL分区表作为一种有效的数据管理技术,能够将大型表划分为多个更小、更易管理的分区,从而提升数据库的性能和可...

MySQL基础篇:DQL数据查询操作_mysql 查

一、基础查询DQL基础查询语法SELECT字段列表FROM表名列表WHERE条件列表GROUPBY分组字段列表HAVING分组后条件列表ORDERBY排序字段列表LIMIT...

MySql:索引的基本使用_mysql索引的使用和原理

一、索引基础概念1.什么是索引?索引是数据库表的特殊数据结构(通常是B+树),用于...