Help with regular expression

Discussion in 'Perl Misc' started by soup_or_power@yahoo.com, Apr 7, 2005.

  1. Guest

    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;
    , Apr 7, 2005
    #1
    1. Advertising

  2. Matija Papec Guest

    X-Ftn-To:

    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
    Matija Papec, Apr 7, 2005
    #2
    1. Advertising

  3. Steven Kuo Guest

    On 7 Apr 2005 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
    Steven Kuo, Apr 7, 2005
    #3
  4. 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
    John W. Krahn, Apr 7, 2005
    #4
  5. * 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
    Fabian Pilkowski, Apr 7, 2005
    #5
  6. Anno Siegel Guest

    Steven Kuo <> wrote in comp.lang.perl.misc:
    > On 7 Apr 2005 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
    Anno Siegel, Apr 8, 2005
    #6
  7. Steven Kuo Guest

    On Fri, 8 Apr 2005, Anno Siegel wrote:

    > Steven Kuo <> wrote in comp.lang.perl.misc:
    >> On 7 Apr 2005 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
    Steven Kuo, Apr 8, 2005
    #7
  8. Steven Kuo wrote:
    > On Fri, 8 Apr 2005, Anno Siegel wrote:
    >
    >> Steven Kuo <> wrote in comp.lang.perl.misc:
    >>
    >>> On 7 Apr 2005 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
    John W. Krahn, Apr 8, 2005
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Anand

    Regular Expression help...

    Anand, Jul 9, 2003, in forum: Perl
    Replies:
    1
    Views:
    1,225
    Eric J. Roode
    Jul 9, 2003
  2. Eric B.
    Replies:
    1
    Views:
    431
    Jim Gibson
    Dec 17, 2004
  3. VSK
    Replies:
    2
    Views:
    2,282
  4. =?iso-8859-1?B?bW9vcJk=?=

    Matching abitrary expression in a regular expression

    =?iso-8859-1?B?bW9vcJk=?=, Dec 1, 2005, in forum: Java
    Replies:
    8
    Views:
    839
    Alan Moore
    Dec 2, 2005
  5. GIMME
    Replies:
    3
    Views:
    11,942
    vforvikash
    Dec 29, 2008
Loading...

Share This Page