Javascript 从整数到整数的高效稀疏映射
我正在使用有限自动机实现一个专门构建的正则表达式引擎。我必须存储数千个州,每个州都有自己的从unicode代码点(或UTF-16代码单元;我还没有决定)到州ID的转换表 在许多情况下,表将非常稀疏,但在其他情况下,它将几乎是满的。在大多数情况下,大多数条目将落入几个具有相同值的连续范围 最简单的实现是查找表,但每个这样的表都会占用大量空间。(范围、值)对的列表将小得多,但速度较慢。二叉搜索树将比列表更快Javascript 从整数到整数的高效稀疏映射,javascript,Javascript,我正在使用有限自动机实现一个专门构建的正则表达式引擎。我必须存储数千个州,每个州都有自己的从unicode代码点(或UTF-16代码单元;我还没有决定)到州ID的转换表 在许多情况下,表将非常稀疏,但在其他情况下,它将几乎是满的。在大多数情况下,大多数条目将落入几个具有相同值的连续范围 最简单的实现是查找表,但每个这样的表都会占用大量空间。(范围、值)对的列表将小得多,但速度较慢。二叉搜索树将比列表更快 是否有更好的方法,也许是利用内置功能?听起来您有两种截然不同的情况(“在许多情况下,表将非常
是否有更好的方法,也许是利用内置功能?听起来您有两种截然不同的情况(“在许多情况下,表将非常稀疏,但在其他情况下,表将几乎满”) 对于稀疏情况,您可能有一个单独的稀疏索引(或几层索引),然后您的实际数据可以存储在一个类型化数组中。因为索引将从整数映射到整数,所以它们也可以表示为类型化数组 查找值的方式如下所示:
对于密集的情况,我不确定。如果密集的情况正好是一个重复键值范围的情况,那么考虑使用类似的东西——简单的相同的连续值被简单地表示为它们的出现次数,然后表示实际值。再一次,使用类型化数组和二进制搜索,甚至可能使用索引来加快搜索速度。不幸的是,JavaScript的内置数据类型——特别是
Map
——对完成这项任务没有太大帮助,因为它们缺乏相关的方法
在大多数情况下,大多数条目将分为几个连续的条目
具有相同值的范围
不过,我们可以利用这一点,并在排序数组上使用二进制搜索策略,前提是转换表不会经常修改
通过在排序数组中存储每个输入范围的最低值,对导致相同状态的连续输入范围进行编码。将相应索引处的状态保留在单独的数组中:
let inputs = [0, 5, 10]; // Input ranges [0,4], [5,9], [10,∞)
let states = [0, 1, 0 ]; // Inputs [0,4] lead to state 0, [5,9] to 1, [10,∞) to 0
现在,给定一个输入,您需要对输入数组执行二进制搜索,类似于:
//返回小于或等于的最大元素的索引
//给定元素,如果没有此类元素,则为未定义元素:
功能floorIndex(已排序,元素){
设low=0;
设high=sorted.length-1;
而(低)>1;
if(已排序的[mid]>元素){
高=中-1;
}else if(已排序[中间]<元素){
低=中+1;
}否则{
中途返回
}
}
返回低-1;
}
//示例:1F600-1F64F范围内的表情符号转换为1:
让变换={
输入:[0x00000、0x1F600、0x1F650],
国家:[0,1,0]
};
让输入=0x1F60B;//自(现代)javascript数组本身是稀疏的,这不应该是内存问题;许多数组元素也可以引用同一个对象,这将在遇到范围时为您节省一些空间。@StephenP问题是关于映射到整数。您必须包装整数才能引用它们(因为它们是基元类型),所以引用实际上会慢一些