Reputation: 55
I have a hash with this structure
{
a => ['1', '2', '', '5', '6', '7', '8'],
b => ['1', '2', '3', '6', '7', '8', '9'],
c => ['2', '', '4', '', '', '8', ''],
}
And I need some like this
{
c => ['2', '4', '8'],
a => ['1', '2', '5', '6', '7', '8'],
b => ['1', '2', '3', '6', '7', '8', '9']
}
How can I delete the ''
values?
Upvotes: 2
Views: 1173
Reputation: 50677
You can directly change list of array references returned by values
as described in perldoc.
use warnings;
my %h = (
'c' => ['2','','4','','','8',''],
'a' => ['1','2','','5','6','7','8'],
'b' => ['1','2','3','6','7','8','9']
);
@$_ = grep defined && length, @$_ for values %h;
and in the case that undef
values should not be filtered out,
@$_ = grep !defined || length, @$_ for values %h;
Upvotes: 11
Reputation: 126762
None of the answers you have seen so far consider the possibility that the hash values may be anything other than simple strings or numbers.
While that may be appropriate to your data, it isn't a safe assumption in general.
This example modifies the hash in place, removing only empty string values and preserving everything else.
Note that, even though it may need to be installed, Data::Dump
is usually a better choice than Data::Dumper
, as shown here.
use strict;
use warnings;
my @alpha = ('a' .. 'm');
my $hash = {
a => ['1', '2', '', '5', '6', '7', '8'],
b => ['1', '2', '3', '6', '7', '8', '9'],
c => ['2', '', '4', '', '', '8', ''],
d => ['5', '', '6', '', undef, '22', '', 'aa', -51.2, \@alpha],
};
for my $list (values %$hash) {
for (my $i = $#{$list}; $i >= 0; --$i) {
my $item = $list->[$i];
splice(@{$list}, $i, 1) if defined $item and $item eq '';
}
}
use Data::Dump;
dd $hash;
output
{
a => [1, 2, 5 .. 8],
b => [1, 2, 3, 6 .. 9],
c => [2, 4, 8],
d => [5, 6, undef, 22, "aa", -51.2, ["a" .. "m"]],
}
Upvotes: 2
Reputation:
since the op wanted to get a hash back, here is a quick solution which works fine :)
use strict;
use warnings;
use Data::Dumper;
use feature 'say';
my %h = (
'c' => ['2','','4','','','8',''],
'a' => ['1','2','','5','6','7','8'],
'b' => ['1','2','3','6','7','8','9']
);
foreach my $keys ( keys %h) {
$h{$keys} = [grep { length $_ } @{$h{$keys}}];
}
say Dumper \%h;
Upvotes: 0
Reputation: 5159
mpapec has already posted a nice succinct answer, but I figured I post my solution too.
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my %hash = ( c => ['2','','4','','','8',''],
a => ['1','2','','5','6','7','8'],
b => ['1','2','3','6','7','8','9'],
);
for my $key (keys %hash) {
my @temp_array = ();
for my $element ( @{$hash{$key}} ) {
if ( $element ne "" ) { # only remove empty strings
push @temp_array, $element;
}
}
$hash{$key}=\@temp_array;
}
print Dumper %hash;
This traverses the whole data structure and maybe that will help if you need to access the elements for other things. Here's the output:
$VAR1 = 'c';
$VAR2 = [
'2',
'4',
'8'
];
$VAR3 = 'a';
$VAR4 = [
'1',
'2',
'5',
'6',
'7',
'8'
];
$VAR5 = 'b';
$VAR6 = [
'1',
'2',
'3',
'6',
'7',
'8',
'9'
];
Upvotes: 2