Search code examples
perlreferencecharacter-arraysslice

using references to point to sliding window array in Perl


here is my problem: I have 2 arrays. One is character array and represents a sliding window. Characters gets shifted from the beginning and pushed at the end. I would like to use a second array to store references to array slices that 'follow' the characters as they move along. Example:

my @char_array = ('h','e','l','l','o','w','o','r','l','d');
my $char_arr_ref=[@char_array[1..$#char_array]]; 
print @$char_arr_ref, "\n"; # slice contains 'elloworld';
shift(@char_array);
push(@char_array), 'x';
print @$char_arr_ref, "\n"; # slice still contains 'elloworld', not 'lloworldx' as I need;

IN other words, I would like to be able to use a second array with references to array slices (as I would do with a pointer array in C for example).

Is there an idiomatic way to do this in Perl?

UPDATE: this is part of a larger program to do fast text searches. I was going to use a hash of references (say, instead of the the 'index' function which is painfully slow. And I need to do this in Perl.


Solution

  • In C, your windows might be implemented using pointer arithmetic.

    const char* s = str+1;
    const char* e = str+len;
    for (const char* p=s; p!=e; ++p) putc(*p);
    

    Except pointer arithmetic wouldn't allow you to resize the buffer (push @char_array, 'x';). Even in C, you'd have to use offsets.

    size_t si = 1;
    size_t ei = len;
    for (size_t i=si; i!=e1; ++i) putc(str[i]);
    

    This is fortunate, because Perl doesn't have pointers, much less pointer arithmetic. But offsets? No problem!

    my @char_array = split //, 'helloworld';
    my ($s, $e) = (1, $#char_array);
    say @char_array[$s..$e];    # elloworld
    shift @char_array;
    push @char_array, 'x';
    say @char_array[$s..$e];    # lloworldx
    

    If we're actually talking about chars, a string would be more efficient.

    my $char_array = 'helloworld';
    my ($s, $e) = (1, length($char_array));
    say substr($char_array, $s, $e-$s+1);    # elloworld
    $char_array =~ s/^.//s;
    $char_array .= 'x';
    say substr($char_array, $s, $e-$s+1);    # lloworldx
    

    In fact, if we're actually talking about chars, we're quite lucky since we can use an lvalue substr and let Perl handle the offsets for us!

    my $char_array = 'helloworld';
    my $substr_ref = \substr($char_array, 1, length($char_array)-1);
    say $$substr_ref;        # elloworld
    $char_array =~ s/^.//s;
    $char_array .= 'x';
    say $$substr_ref;        # lloworldx
    

    Way easier than C with more or less all the same benefits!