Deleting blank elements from a list

J

Just in

If I do this:-

use strict;
use warnings;

my @Arr1 = split /\D+/, $Str1;
my @Arr2 = split /\D+/, $Str2;

foreach my $i(0..$#Arr1)
{
foreach my $j(0..$#Arr2)
{
if($Arr1[$i] eq $Arr2[$j])
{
delete $Arr2[$j];
}
}
}

In some instances @Arr2 ends up looking like this ('', '', 'Value3',
Value4', '')

How can I make @Arr2 = ('Value3', 'Value4') i.e. $#Arr2 == 1
rather than 4?

Cheers,
Just in
 
B

Bob Walton

Just said:
If I do this:-

use strict;
use warnings;

my @Arr1 = split /\D+/, $Str1;
my @Arr2 = split /\D+/, $Str2;

foreach my $i(0..$#Arr1)
{
foreach my $j(0..$#Arr2)
{
if($Arr1[$i] eq $Arr2[$j])
{
delete $Arr2[$j];
}
}
}

In some instances @Arr2 ends up looking like this ('', '', 'Value3',
Value4', '')

How can I make @Arr2 = ('Value3', 'Value4') i.e. $#Arr2 == 1
rather than 4?

Cheers,
Just in


You could use the splice() function instead of delete() to remove
element from @Arr2 instead of just undef'ing them like delete() does:

perldoc -f splice

But you should really revamp your entire algorithm, since it is way slow
(order n^2). Maybe something like:

{
my %h;
@h{@Arr2}=(0..$#Arr2);
delete @h{@Arr1};
@Arr2=sort {$h{$a}<=>$h{$b}} keys %h;
}

You could apply the Schwarzian Transform to the sort to further improve
the efficiency.
 
G

Gunnar Hjalmarsson

Just said:
If I do this:-

use strict;
use warnings;

my @Arr1 = split /\D+/, $Str1;
my @Arr2 = split /\D+/, $Str2;

foreach my $i(0..$#Arr1)
{
foreach my $j(0..$#Arr2)

To increase efficiency and prevent uninitialized warnings:

foreach my $j (reverse 0..$#Arr2)
{
if($Arr1[$i] eq $Arr2[$j])
{
delete $Arr2[$j];

splice @Arr2, $j, 1;
}
}
}

In some instances @Arr2 ends up looking like this ('', '',
'Value3', Value4', '')

How can I make @Arr2 = ('Value3', 'Value4') i.e. $#Arr2 == 1
rather than 4?

See suggestions above. You should also study

perldoc -q duplicate
 
J

John W. Krahn

Just said:
If I do this:-

use strict;
use warnings;

my @Arr1 = split /\D+/, $Str1;
my @Arr2 = split /\D+/, $Str2;

You should probably use the match operator for that so that you don't
get an empty string as the first element of the array.

my @Arr1 = $Str1 =~ /\d+/g;
my @Arr2 = $Str2 =~ /\d+/g;

foreach my $i(0..$#Arr1)
{
foreach my $j(0..$#Arr2)
{
if($Arr1[$i] eq $Arr2[$j])
{
delete $Arr2[$j];
}
}
}

In some instances @Arr2 ends up looking like this ('', '', 'Value3',
Value4', '')

It would look more like (undef, undef, 'Value3', 'Value4', undef)

How can I make @Arr2 = ('Value3', 'Value4') i.e. $#Arr2 == 1
rather than 4?

This will do what you want:

my $regex = qr[\b@{[ join '|', $Str1 =~ /\d+/g ]}\b];
my @Arr2 = grep !/$regex/, $Str2 =~ /\d+/g;



John
 
J

John W. Krahn

Just said:
If I do this:-

use strict;
use warnings;

my @Arr1 = split /\D+/, $Str1;
my @Arr2 = split /\D+/, $Str2;

You should probably use the match operator for that so that you don't
get an empty string as the first element of the array.

my @Arr1 = $Str1 =~ /\d+/g;
my @Arr2 = $Str2 =~ /\d+/g;

foreach my $i(0..$#Arr1)
{
foreach my $j(0..$#Arr2)
{
if($Arr1[$i] eq $Arr2[$j])
{
delete $Arr2[$j];
}
}
}

In some instances @Arr2 ends up looking like this ('', '', 'Value3',
Value4', '')

It would look more like (undef, undef, 'Value3', 'Value4', undef)

How can I make @Arr2 = ('Value3', 'Value4') i.e. $#Arr2 == 1
rather than 4?

This will do what you want:

my $regex = qr[\b(?:mad:{[ join '|', $Str1 =~ /\d+/g ]})\b];
my @Arr2 = grep !/$regex/, $Str2 =~ /\d+/g;


John
 
D

dutone

Gunnar Hjalmarsson said:
Just said:
If I do this:-

use strict;
use warnings;

my @Arr1 = split /\D+/, $Str1;
my @Arr2 = split /\D+/, $Str2;

foreach my $i(0..$#Arr1)
{
foreach my $j(0..$#Arr2)

To increase efficiency and prevent uninitialized warnings:

foreach my $j (reverse 0..$#Arr2)
{
if($Arr1[$i] eq $Arr2[$j])
{
delete $Arr2[$j];

splice @Arr2, $j, 1;
}
}
}

In some instances @Arr2 ends up looking like this ('', '',
'Value3', Value4', '')

How can I make @Arr2 = ('Value3', 'Value4') i.e. $#Arr2 == 1
rather than 4?

See suggestions above. You should also study

perldoc -q duplicate


You suggested....

To increase efficiency and prevent uninitialized warnings:
foreach my $j (reverse 0..$#Arr2)

Can you tell me how this will increase efficiency?

Thanks
 
G

Gunnar Hjalmarsson

dutone said:
Can you tell me how this will increase efficiency?

Fewer iterations under certain conditions, and (I think) more accurate
result. Please consider this code:

my $Str1 = '1 2 3 4 5';
my $Str2 = '1 1 2 2 6';
my $iter;

my @Arr1 = split /\D+/, $Str1;
my @Arr2 = split /\D+/, $Str2;

for my $i (0..$#Arr1) {
for my $j (0..$#Arr2) {
if ($Arr1[$i] eq $Arr2[$j]) {
splice @Arr2, $j, 1;
}
$iter++;
}
}

print "Left in \@Arr2: @Arr2\n";
print "$iter iterations\n";

Besides a couple of "uninitialized" warnings it outputs:
Left in @Arr2: 1 2 6
18 iterations

But if you change

for my $j (0..$#Arr2) {

to

for my $j (reverse 0..$#Arr2) {

it outputs:
Left in @Arr2: 6
11 iterations

(and no warnings).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top