s_gaurav1091 has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks I have an array which conatains different dates in the form
092205 092305 092605
Now i want to modify the contents of my array so that it contains element in the form
09/22/05 09/23/05 09/29/05
and so on..its just that i want to insert slash among month ,day and year.. help plz

Replies are listed 'Best First'.
Re: modify the contents of an array
by blazar (Canon) on Sep 29, 2005 at 11:29 UTC
    if you trust those dates to be in the format above, then
    $_=join '/', unpack 'A2' x 3, $_ for @arr;
Re: modify the contents of an array
by Joost (Canon) on Sep 29, 2005 at 11:21 UTC
Re: modify the contents of an array
by prasadbabu (Prior) on Sep 29, 2005 at 11:18 UTC

    I think this will help you

    @arr = ('092205', '092305', '092605'); map {s/^(\d{2})(\d{2})(\d{2})/$1\/$2\/$3/} @arr; $" ="\n"; print "@arr";

    Prasad

      No it won't. It will print the return values of those s///'s which happens to be 1.

      Also from perlstyle:

      Avoid using grep() (or map()) or `backticks` in a void context, that is, when you just throw away their return values. Those func- tions all have return values, so use them. Otherwise use a fore- ach() loop or the system() function instead.
        You would be right if prasadbabu had written:
        @arr = map {s/^(\d{2})(\d{2})(\d{2})/$1\/$2\/$3/} @arr;
        But he didn't. He rightly ignored the return values of s/// (if you write s/^(\d{2})(\d{2})(\d{2})/$1\/$2\/$3/ for @arr, you are ignoring the return value of s/// just as much as when using map in void context), and went of the side effects of s/// - the main feature of s///.

        blazar you are absolutely right. But the above coding works for me, i tested and then only posted.

        Hereafter i try to avoid these kind of mistakes.

        Prasad

      I'd have used foreach instead of map, but other than that... nice simple solution.

Re: modify the contents of an array
by Skeeve (Parson) on Sep 29, 2005 at 12:07 UTC
    Just to add my 2 Euro-Cent:
    chomp(@array=<DATA>); s:(..)(?!$):$1/:g for @array; print join "\n", @array, ''; __DATA__ 092205 092305 092605 nonsense
    Yes! This will create nonsense for non matching lines, like the last one. But I wanted to come up with a shorter RE ;-)

    $\=~s;s*.*;q^|D9JYJ^^qq^\//\\\///^;ex;print
      Hi, Your solution seems to be working perfectly but I am still wondering how it happened.I am a beginner in perl ,if you dont mind can you just explain me the solution
        No problem.

        The key thing is the regular expression (..)(?!$)
        This means: Match any 2 chars ".." and remember them "()" if they are not followed by the string's end "(?!$)".
        If such a match is found, it is replaced by the 2 chars found "$1" and a slash appended, so "$1/".
        Hmmm... Not so well my explanation, I think. The idea is to find any two characters and append a slash to them The only exception is at the end of the string where no slash may be added.

        This works well for your data, but as soon as you got other data, it will produce nonsense by inserting slashes every 2 characters.

        $\=~s;s*.*;q^|D9JYJ^^qq^\//\\\///^;ex;print
Re: modify the contents of an array
by srdst13 (Pilgrim) on Sep 29, 2005 at 11:22 UTC
    How about:
    my @dates = (qw/092205 092305 092605/); my @newdates; foreach my $date (@dates) { my ($month,$day,$year) = ($date =~ /(\d\d)(\d\d)(\d\d)/); push @newdates,join('/',$month,$day,$year); }
    Of course, you can do any particular manipulation of $month,$day,$year that you like, such as changing $year to its 4-digit equivalent, etc.

    Sean
Re: modify the contents of an array
by tomazos (Deacon) on Sep 29, 2005 at 11:44 UTC
    Consider whether in the larger picture of your code using one of the Date:: modules may be a better approach.

    It may or may not be.

    -Andrew.


    Andrew Tomazos  |  andrew@tomazos.com  |  www.tomazos.com
Re: modify the contents of an array
by dannoura (Pilgrim) on Sep 29, 2005 at 14:45 UTC

    How about:

    my @arr = qw/092205 092305 092605/; foreach (@arr) {$_ = sprintf "%d%d/%d%d/%d%d", split //} print "@arr";
      Even slower than the s/// suggestion.
      #!/usr/bin/perl use strict; use warnings; use Benchmark qw 'cmpthese'; our @dates = (qw [092205 092305 092605]) x 100; our (@sub, @pck, @mth, @spf,); cmpthese(-10, { sub => '@sub = @dates; for (@sub) {s{(\d{2})(\d{2})(\d{2})}{$1/$2/ +$3}}', pck => '@pck = @dates; for (@pck) {$_ = join "/", unpack "A2 A2 A2 +", $_}', mth => '@mth = @dates; for (@mth) {$_ = join "/", /../g}', spf => '@spf = @dates; for (@spf) {$_ = sprintf "%d%d/%d%d/%d%d", +split //}', }); __END__ Rate spf sub mth pck spf 368/s -- -33% -60% -69% sub 548/s 49% -- -40% -53% mth 909/s 147% 66% -- -22% pck 1171/s 218% 114% 29% --
Re: modify the contents of an array
by radiantmatrix (Parson) on Sep 29, 2005 at 15:11 UTC

    It appears blazar has the best approach. I added data validation to, and bencmarked, the two main solutions (regexes and unpack), as well as doing the same thing with sprintf (just for fun).

    @my_array = <DATA>; use Benchmark ':all'; sub regex_method { my $array = [@_]; for (@$array) { next unless /^\d{6}\s*$/; ## validate data s:(\d{2})(?!$):$1/:g; } } sub sprint_method { my $array = [@_]; for (@$array) { next unless /^\d{6}\s*$/; ## validate data $_ = sprintf "%d%d/%d%d/%d%d", split('',$_); } } sub unpack_method { my $array = [@_]; for (@$array) { next unless /^\d{6}\s*$/; ## validate data $_=join '/', unpack 'A2' x 3, $_ for @arr; } } cmpthese( 50000, { 'regex' => sub { regex_method(@my_array) }, 'sprintf' => sub { sprint_method(@my_array) }, 'unpack' => sub { unpack_method(@my_array) }, }); __DATA__ 010203 020304 012398 122399

    With these results (representative of many runs):

    Rate sprintf regex unpack sprintf 20383/s -- -23% -79% regex 26441/s 30% -- -73% unpack 96899/s 375% 266% --
    <-radiant.matrix->
    Larry Wall is Yoda: there is no try{} (ok, except in Perl6; way to ruin a joke, Larry! ;P)
    The Code that can be seen is not the true Code
    "In any sufficiently large group of people, most are idiots" - Kaa's Law
Re: modify the contents of an array
by ryanc (Monk) on Sep 30, 2005 at 16:27 UTC
    how about:
    @arr = ('092205', '092305', '092605'); $_ = join "/", unpack("a2a2a2", $_) for @arr;

    later on:
    print "$_\n" for @arr;

    to verify the values.
    should work and is nice and small.

    later.
    ryanc
      oops, didn't read the reply above. looks like someone already offered up the 'unpack' way.