Matlab 低复杂度整数向量的有效表示

Matlab 低复杂度整数向量的有效表示,matlab,Matlab,设V为整数向量,L为V的长度 现在,假设V中不同值的数量N远小于L 还可以假设V已排序,因此可以将其解释为N个连续常量“块”的串联 最后,我们可以假设,一旦初始化,V从此是只读的(也称为不可变的) (在我目前使用的例子中,L在106到107之间,N大约是20。) 将这种低复杂度的数据存储在标准的MATLAB L-长向量中是浪费的。MATLAB是否有任何内置的数据结构 与正则向量具有相同的接口(例如,可以使用表达式V(k)读取其第k个元素,使用V(end)读取其最后一个元素,使用V(p:q)读取位

V
为整数向量,L为
V
的长度

现在,假设
V
中不同值的数量N远小于L

还可以假设
V
已排序,因此可以将其解释为N个连续常量“块”的串联

最后,我们可以假设,一旦初始化,
V
从此是只读的(也称为不可变的)

(在我目前使用的例子中,L在106到107之间,N大约是20。)

将这种低复杂度的数据存储在标准的MATLAB L-长向量中是浪费的。MATLAB是否有任何内置的数据结构

  • 与正则向量具有相同的接口(例如,可以使用表达式
    V(k)
    读取其第k个元素,使用
    V(end)
    读取其最后一个元素,使用
    V(p:q)
    读取位置范围等)
  • 使用的存储空间比整数大小的L×小得多
  • ?


    顺便说一句,这里的问题让人想起稀疏数组表示,但不完全相同(至少是AFAICT)


    好的,这是我的解决方案,基于gariepy的回答:

    block_sizes = [5, 4, 3, 2];
    block_values = 1000 + (1:numel(block_sizes));
    interpolation_table = [0 cumsum(block_sizes)];
    V = @(i) interp1(interpolation_table, [NaN block_values], i, 'next');
    V(0)
    ans =
       NaN
    
    V(1:5)
    ans =
            1001        1001        1001        1001        1001
    
    V(6:9)
    ans =
            1002        1002        1002        1002
    
    V(10:12)
    ans =
            1003        1003        1003
    
    V(13:14)
    ans =
            1004        1004
    
    V(15)
    ans =
       NaN
    
    但它有一个小小的疣子:

    V(end)
    ans =
            1001
    
    (如果它在给定
    end
    作为参数时引发异常,而不是给出完全疯狂的答案,那会更好。)



    1当然,我知道我总是可以尝试自己实现这样的东西,但如果可以避免的话,我宁愿不重新发明轮子。

    表示此数据的一种可能方法是插值表

    假设
    vec
    是长度L向量。首先,计算出现的次数:

    [num_occurrences, y_values] = hist(vec, unique(vec));
    
    然后,构建插值表示:

    interp_table = zeros(1,length(y_values) + 1);
    interp_table(1) = 1;
    y_values(end+1) = y_values(end) + 1;  % Need to create a "fake" value at the end of the interpolation table
    for i = 2:length(y_values)
        interp_table(i) = interp_table(i-1) + num_occurrences(i-1);
    end
    
    最后,定义一个函数句柄,为您提供所需的“类似数组”的访问

    my_fun = @(x) interp1(interp_table, y_values, x, 'previous');
    
    例如:

    >> vec = [1 1 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 ];
    >> my_fun(1)
    ans =
         1
    >> my_fun(2)
    ans =
         1
    >> my_fun(3)
    ans =
         2
    >> my_fun(6)
    ans =
         2
    >> my_fun(7)
    ans =
         2
    >> my_fun(8)
    ans =
         3
    >> my_fun(17)
    ans =
         3
    >> my_fun(18)  %% This is vec(L+1), so it should never be needed
    ans =
         4
    >> my_fun(19)  %% Above index L+1, values are not defined
    ans =
       NaN
    
    示例演示了一个小警告:不应使用my_fun(L)以上的值,其中L是由插值表表示的原始向量的长度。因此,这提供了类似于数组的访问,尽管不能直接计算插值表的“长度”

    编辑:请注意,您可以使用此插值函数进行范围编辑:

    >> my_fun(1:17)
    ans =
      Columns 1 through 15
         1     1     2     2     2     2     2     3     3     3     3     3     3     3     3
      Columns 16 through 17
         3     3
    

    简短的回答是否定的。不过,根据您使用该向量的方式,可能有一种方法可以实现您想要的,而无需将整个向量存储在内存中。如果你给我们举一个用例的例子,也许我们能帮上忙。@Suever:我已经举了一个例子:L=100万,N=20。这些是问题中唯一的参数。对,但是你的目标只是创建这个向量,还是你想用这个向量做点什么。如果只是为了创建它,那么您需要推出自己的实现。如果你想做某事,那么可能有一种内在的方式。@Suever:现在我明白你的意思了。不,我在寻找一般的数据结构。我想答案是“不”。这就差不多解决了。谢谢,好主意。我把它改了一点。请参阅我的编辑。