Help with regular expression

  • Follow


I need help with this regex. It looks the keys of fdat are searched for
"$prefix" and fdat hash is deleted. I have no idea what the map is
trying to do. Thanks for your help.

 debug my %indices  = map { (/^\Q$prefix.\E(.+)/), $_ } grep { delete
$fdat{$_} } grep /^\Q$prefix.\E/, keys %fdat;

0
Reply soup_or_power (214) 4/7/2005 5:16:13 PM

X-Ftn-To: soup_or_power@yahoo.com 

soup_or_power@yahoo.com wrote:
>I need help with this regex. It looks the keys of fdat are searched for
>"$prefix" and fdat hash is deleted. I have no idea what the map is
>trying to do. Thanks for your help.

map is producing hash pairs, where keys are striped %fdat keys (and values
are unmodified %fdat keys).

> debug my %indices  = map { (/^\Q$prefix.\E(.+)/), $_ } grep { delete
>$fdat{$_} } grep /^\Q$prefix.\E/, keys %fdat;

#untested
my %indices  = 
  map  { /^\Q$prefix.\E(.+)/, $_ }
  grep /^\Q$prefix./ && delete $fdat{$_},
  keys %fdat;

This is somehow shorter but..

my %indices  = 
  map {
    my $k = $_;
    s!^\Q$prefix.!! && delete $fdat{$k} ? ($_ => $k) : ();
  }
  keys %fdat;

... here we are using only one regex so it should be little faster if speed
counts.



-- 
Matija
0
Reply Matija 4/7/2005 6:04:03 PM


On 7 Apr 2005 soup_or_power@yahoo.com wrote:

> I need help with this regex. It looks the keys of fdat are searched for
> "$prefix" and fdat hash is deleted. I have no idea what the map is
> trying to do. Thanks for your help.
> 
>  debug my %indices  = map { (/^\Q$prefix.\E(.+)/), $_ } grep { delete
> $fdat{$_} } grep /^\Q$prefix.\E/, keys %fdat;
 


That's likely to be wrong as 'map' may return an odd number of elements
to %indices.  Perhaps the intent was something like this?

my %indices = 
    map { /^\Q$prefix.\E(.+)/ ? $1 : '' , $_ }
    grep { delete  $fdat{$_} }
    grep /^\Q$prefix.\E/,
    keys %fdat;                                   


That's still too obfuscated for my tastes.  I'd prefer:

my %indices;
my @keys_to_remove_from_fdat;
 
for my $k (keys %fdat)
{
    if ($k =~ /^\Q$prefix.\E(.*)/)
    {
	$indices{$1} = $k;
	push @keys_to_remove_from_fdat, $k;
    }
}

delete @fdat{@keys_to_remove_from_fdat};

-- 
Hope this helps,
Steven

0
Reply Steven 4/7/2005 6:42:17 PM

soup_or_power@yahoo.com wrote:
> I need help with this regex. It looks the keys of fdat are searched for
> "$prefix" and fdat hash is deleted. I have no idea what the map is
> trying to do. Thanks for your help.
> 
>  debug my %indices  = map { (/^\Q$prefix.\E(.+)/), $_ } grep { delete
> $fdat{$_} } grep /^\Q$prefix.\E/, keys %fdat;

Well, let's have a look:

john@perl john $ perl -le'use Data::Dumper;
my %x = qw/ abc.123 2 abc.234 3 abc.345 4 abc.456 5 abc.567 6 xyz.123 7 
xyz.234 8 xyz.345 9 /;
print Dumper \%x;
my $prefix = q/abc/;
my %y = map { (/^\Q$prefix.\E(.+)/), $_ } grep { delete $x{$_} } grep 
/^\Q$prefix.\E/, keys %x;
print Dumper \%x, \%y;
'
$VAR1 = {
           'xyz.345' => '9',
           'abc.123' => '2',
           'abc.456' => '5',
           'xyz.234' => '8',
           'abc.345' => '4',
           'abc.567' => '6',
           'xyz.123' => '7',
           'abc.234' => '3'
         };

$VAR1 = {
           'xyz.345' => '9',
           'xyz.234' => '8',
           'xyz.123' => '7'
         };
$VAR2 = {
           '345' => 'abc.345',
           '456' => 'abc.456',
           '123' => 'abc.123',
           '567' => 'abc.567',
           '234' => 'abc.234'
         };



John
-- 
use Perl;
program
fulfillment
0
Reply John 4/7/2005 7:18:29 PM

* Steven Kuo schrieb:
> 
> That's still too obfuscated for my tastes.  I'd prefer:
> 
> my %indices;
> my @keys_to_remove_from_fdat;
> for my $k (keys %fdat) {
>     if ($k =~ /^\Q$prefix.\E(.*)/) {
>         $indices{$1} = $k;
>         push @keys_to_remove_from_fdat, $k;
>     }
> }
> delete @fdat{@keys_to_remove_from_fdat};

It seems that the values of the hash %indices are the same as the
elements of the array @keys_to_remove_from_fdat. You could write


    my %indices;
    for ( keys %fdat ) {
        $indices{$1} = $_ if /^\Q$prefix.\E(.*)/;
    }
    delete @fdat{ values %indices };


regards,
fabian
0
Reply Fabian 4/7/2005 8:24:43 PM

Steven Kuo  <skuo@mtwhitney.nsc.com> wrote in comp.lang.perl.misc:
> On 7 Apr 2005 soup_or_power@yahoo.com wrote:
> 
> > I need help with this regex. It looks the keys of fdat are searched for
> > "$prefix" and fdat hash is deleted. I have no idea what the map is
> > trying to do. Thanks for your help.
> > 
> >  debug my %indices  = map { (/^\Q$prefix.\E(.+)/), $_ } grep { delete
> > $fdat{$_} } grep /^\Q$prefix.\E/, keys %fdat;
>  
> 
> 
> That's likely to be wrong as 'map' may return an odd number of elements

How?  The first grep (chronologically, so textually the last one) makes
sure that /^\Q$prefix.\E/ will always match, so the map block will
always return exactly two elements.

I agree that the operation could be better written.

Anno
0
Reply anno4000 4/8/2005 9:18:09 AM

On Fri, 8 Apr 2005, Anno Siegel wrote:

> Steven Kuo  <skuo@mtwhitney.nsc.com> wrote in comp.lang.perl.misc:
>> On 7 Apr 2005 soup_or_power@yahoo.com wrote:
>>
>>> I need help with this regex. It looks the keys of fdat are searched for
>>> "$prefix" and fdat hash is deleted. I have no idea what the map is
>>> trying to do. Thanks for your help.
>>>
>>>  debug my %indices  = map { (/^\Q$prefix.\E(.+)/), $_ } grep { delete
>>> $fdat{$_} } grep /^\Q$prefix.\E/, keys %fdat;
>>
>>
>>
>> That's likely to be wrong as 'map' may return an odd number of elements
>
> How?  The first grep (chronologically, so textually the last one) makes
> sure that /^\Q$prefix.\E/ will always match, so the map block will
> always return exactly two elements.
>
> I agree that the operation could be better written.
>




The problem is subtle.  However there is a string that will 
pass through the grep "filter" pattern but fail to match the 
map "key generation" pattern.  In particular, this string:

     $prefix . '.';

The failed match in list context does not return a empty string
but instead omits an element.

One can see this more clearly if we return the output to an
array:

use Data::Dumper;

my $prefix = 'foo';
my @count_items =
     map { (/^\Q$prefix.\E(.+)/), $_ }
     grep /^\Q$prefix.\E/,
     (
 	$prefix . '.',
 	$prefix . '.something else'
     );

print Dumper \@count_items;

$VAR1 = [
           'foo.',
 	  'something else',
 	  'foo.something else'
 	];

There are an odd number of elements!  Worse is that perl will,
without warnings enabled, tacitly accept this and construct a hash
with corrupted data:

my %bad_results =
     map { (/^\Q$prefix.\E(.+)/), $_ }
     grep /^\Q$prefix.\E/,
     (
 	$prefix . '.',
 	$prefix . '.something else'
     );


print Dumper \%bad_results;

$VAR1 = {
           'foo.something else' => undef,
           'foo.' => 'something else'
         };


I'm not the OP, who may be willing to assert that "my data will never
look like that".

The alternative code I proposed, however, does not return an odd
number of elements, regardless of the form of input data.

-- 
Regards,
Steven
0
Reply Steven 4/8/2005 5:07:11 PM

Steven Kuo wrote:
> On Fri, 8 Apr 2005, Anno Siegel wrote:
> 
>> Steven Kuo  <skuo@mtwhitney.nsc.com> wrote in comp.lang.perl.misc:
>>
>>> On 7 Apr 2005 soup_or_power@yahoo.com wrote:
>>>
>>>> I need help with this regex. It looks the keys of fdat are searched for
>>>> "$prefix" and fdat hash is deleted. I have no idea what the map is
>>>> trying to do. Thanks for your help.
>>>>
>>>>  debug my %indices  = map { (/^\Q$prefix.\E(.+)/), $_ } grep { delete
>>>> $fdat{$_} } grep /^\Q$prefix.\E/, keys %fdat;
>>>
>>> That's likely to be wrong as 'map' may return an odd number of elements
>>
>> How?  The first grep (chronologically, so textually the last one) makes
>> sure that /^\Q$prefix.\E/ will always match, so the map block will
>> always return exactly two elements.
>>
>> I agree that the operation could be better written.
> 
> The problem is subtle.  However there is a string that will pass through 
> the grep "filter" pattern but fail to match the map "key generation" 
> pattern.  In particular, this string:
> 
>     $prefix . '.';
> 
> The failed match in list context does not return a empty string
> but instead omits an element.

That can be "fixed" by adding one character to the original:

my %indices = map { (/^\Q$prefix.\E(.+)/), $_ } grep { delete $fdat{$_} } grep 
/^\Q$prefix.\E./, keys %fdat;


John
-- 
use Perl;
program
fulfillment
0
Reply John 4/8/2005 10:13:15 PM

7 Replies
68 Views

(page loaded in 0.094 seconds)

Similiar Articles:













7/23/2012 10:19:31 AM


Reply: