Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I tie an array slice to the original array so all changes that are made to one are made to both?

I need to be able to tie an array slice to the original array in such a way that any changes made to the original array (including removing elements) will also be made to the array slice. Is there a way to do this?


The following example does not work how I want it to, but it is simply there to demonstrate the point I am trying to make.

Example:

my @array = 1 .. 10;
my @slice = @array[3 .. 8];

splice @array, 5, 2;

print "ARRAY: ";
print join ', ', @array;
print "\n";

print "SLICE: ";
print join ', ', @slice;

Output:

ARRAY: 1, 2, 3, 4, 5, 8, 9, 10
SLICE: 4, 5, 6, 7, 8, 9

What I am looking for is a way to tie the slice to the original array so the output would look like this instead:

ARRAY: 1, 2, 3, 4, 5, 8, 9, 10
SLICE: 4, 5, 8, 9

Removing 6 and 7 from the original array would also remove it from the array slice.

How can I achieve something like this?

like image 231
tjwrona1992 Avatar asked Aug 15 '16 18:08

tjwrona1992


2 Answers

Updated post as requested using Object oriented method. Maintained original response after <========> Line

Here's the object oriented approach as mentioned in comments.
Sample.pm

package Sample;
use strict;
use warnings;
use Exporter qw(import);
use List::MoreUtils qw(first_index);
our @y = qw (3 4 5 6 7 8 9); # Add your method of acquiring @y value here
our @EXPORT = qw (SpliceV2 @y);

##  Your Splice Version 2

sub SpliceV2(@) {
my ($position,$length,@x) = @_;
for (my $i=1;$i<=$length;$i++) {
my $removeditem = $x[$position];
my $remove = first_index { $_ eq $removeditem } @y;
splice @x, $position, 1;
splice @y, $remove, 1;
}

return @x;
}

1;

Main script:

#!/usr/bin/perl
use Sample;
my @x = qw(1 2 3 4 5 6 7 8 9 10);

@x = SpliceV2(4,2,@x);
print "X: @x\n";
print "Y: @y\n";

Original post below <==========> Assuming the items you are removing are unique like if you are basing it on primary keys of a database, then you can use first_index from List::MoreUtils;

Here's a sample.

use List::MoreUtils qw(first_index);
my @x = qw (1 2 3 4 5 6 7 8 9 10);
my @y = qw (4 5 6 7 8 9);

## Let's say you want to remove 2 items after the 5th index

my $position = 5;
my $length = 2;

##      Get the value of items to remove first

for (my $i=1;$i<=$length;$i++) {
  my $removeditem = $x[$position];
  my $remove = first_index { $_ eq $removeditem } @y;
  splice @x, $position, 1;
  splice @y, $remove, 1;
}
print "Array X\n";
print "$_," foreach(@x);
print "\nArray Y\n";
print "$_," foreach(@y);
print "\n";

You should get the result you wanted.

Array X
1,2,3,4,5,8,9,10,
Array Y
4,5,8,9,
like image 120
hashtagjet Avatar answered Oct 31 '22 07:10

hashtagjet


As has been said, that's a tall order. The short answer is no. A slice creates a copy of the elements.

Perl does have a Tie feature that might be just the trick.

perltie - how to hide an object class in a simple variable

So it fundamentally changes what a variable is behind the scenes. A whole world of possibilities opens up, and your scenario just might be in there.

perltie on perldoc.perl.org

like image 39
Able Mac Avatar answered Oct 31 '22 06:10

Able Mac