Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Using the map function

by cspctec (Sexton)
on Jul 10, 2013 at 17:16 UTC ( #1043506=perlquestion: print w/ replies, xml ) Need Help??
cspctec has asked for the wisdom of the Perl Monks concerning the following question:

I have the following data in an array:
CPU Temp = 30 GFX Temp = 45 RAM Temp = 40 CPU Status = OK GFX Status = OK RAM Status = OK
Basically I need to copy everything above the blank line and below the blank line into new, separate arrays, while leaving the array with this data intact.

I don't know how to do this. Is the perl map function a good way to do this? I have this code, but its not working...

@temp = map { /^\s*$/ } @status;
Where @temp would be the data above the blank line and @status is the array with the original data. I think my regex is just counting the number of matches, cause I get 1 as output, but I don't know how to fix it.

Comment on Using the map function
Select or Download Code
Re: Using the map function
by MidLifeXis (Prior) on Jul 10, 2013 at 17:33 UTC

    map transforms data, grep selects data. Use grep.

    Note: if you use @temp anywhere more than 1 or two lines away (and even then I would do this), rename it to @temperature. @temp means to me, a potential future maintenance programmer, that this is a short lived, non persistent, temporary variable.

    --MidLifeXis

Re: Using the map function
by frozenwithjoy (Curate) on Jul 10, 2013 at 17:41 UTC

    Here is an approach that works and is easy to read:

    #!/usr/bin/env perl use strict; use warnings; my @status = <DATA>; my @temp; for (@status) { last if /^\s*$/; push @temp, $_; } print @temp; __DATA__ CPU Temp = 30 GFX Temp = 45 RAM Temp = 40 CPU Status = OK GFX Status = OK RAM Status = OK

    Output:

    CPU Temp = 30 GFX Temp = 45 RAM Temp = 40

    UPDATE: The following results in two arrays (one for temperature and one with status)

    #!/usr/bin/env perl use strict; use warnings; use feature 'say'; my @data = <DATA>; my @status = @data; my @temperature; for (@data) { shift @status; last if /^\s*$/; push @temperature, $_; } say "Temperature:"; print @temperature; say "Status:"; print @status; __DATA__ CPU Temp = 30 GFX Temp = 45 RAM Temp = 40 CPU Status = OK GFX Status = OK RAM Status = OK

    Output:

    Temperature: CPU Temp = 30 GFX Temp = 45 RAM Temp = 40 Status: CPU Status = OK GFX Status = OK RAM Status = OK
Re: Using the map function
by Skeeve (Vicar) on Jul 10, 2013 at 18:27 UTC
    Here is a version that's not easy to read but was fun to write ;)
    #!/usr/bin/perl use strict; use warnings; my (@data, @temperature, @status); @temperature= grep { /\d/ or push(@status, $_) and undef } @data= grep !/^\s*$/, <DATA>; print "Temperature:\n"; print @temperature; print "Status:\n"; print @status; __DATA__ CPU Temp = 30 GFX Temp = 45 RAM Temp = 40 CPU Status = OK GFX Status = OK RAM Status = OK

    s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
    +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
Re: Using the map function
by 2teez (Priest) on Jul 10, 2013 at 18:28 UTC

    Hi cspctec,
    For me, using HASH of ARRAYs, could easily get this done for you like so:

    use warnings; use strict; use Data::Dumper; my %hash; while (<DATA>) { chomp; next if /^\s*$/; my $key = $1 if /\w+?\s+?(.+?)\s+/; push @{ $hash{$key} }, $_; } print Dumper \%hash; __DATA__ CPU Temp = 30 GFX Temp = 45 RAM Temp = 40 CPU Status = OK GFX Status = OK RAM Status = OK
    ... produces ...
    $VAR1 = { 'Temp' => [ 'CPU Temp = 30 ', 'GFX Temp = 45 ', 'RAM Temp = 40 ' ], 'Status' => [ 'CPU Status = OK ', 'GFX Status = OK ', 'RAM Status = OK' ] };

    For more info. Please see perldsc
    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me
Re: Using the map function
by johngg (Abbot) on Jul 10, 2013 at 18:56 UTC

    I wonder if you would do better with two hashes rather than two arrays. You could join your array with newlines and open a filehandle against a reference to the resultant scalar. You could then read it in paragraph mode one record at a time and use splits in maps to populate the hashes.

    $ perl -Mstrict -Mwarnings -MData::Dumper -E ' my @array = ( q{CPU Temp = 30}, q{GFX Temp = 45}, q{RAM Temp = 40}, q{}, q{CPU Status = OK}, q{GFX Status = OK}, q{RAM Status = OK}, ); open my $inFH, q{<}, \ do { join qq{\n}, @array } or die $!; my( %temps, %stats ); { local $/ = q{}; %temps = map { split m{\s+=\s+} } map { split m{\n} } scalar <$inFH>; %stats = map { split m{\s+=\s+} } map { split m{\n} } scalar <$inFH>; } print Data::Dumper ->new( [ \ %temps, \ %stats ], [ qw{ *temps *stats } ] ) ->Sortkeys( 1 ) ->Dumpxs();' %temps = ( 'CPU Temp' => '30', 'GFX Temp' => '45', 'RAM Temp' => '40' ); %stats = ( 'CPU Status' => 'OK', 'GFX Status' => 'OK', 'RAM Status' => 'OK' ); $

    I hope this is helpful.

    Cheers,

    JohnGG

Re: Using the map function
by davido (Archbishop) on Jul 11, 2013 at 00:08 UTC

    You're really just partitioning an array. Slices are handy, but first you have to find the pivot point.

    use List::MoreUtils qw( first_index ); sub partition { my $regex = shift; my $part = first_index { $_ =~ $regex } @_; return [ @_[ 0 .. $part - 1 ] ], [ @_[ $part + 1 .. $#_ ] ]; } my @array = ( 'CPU Temp = 30', 'GFX Temp = 45', 'RAM Temp = 40', ' ', # Space (pivot). 'CPU Status = OK', 'GFX Status = OK', 'RAM Status = OK', ); my( $temp, $status ) = partition( qr/^\s*$/, @array ); { local $" = ", "; print "Temp: ( @{$temp} )\n"; print "Status: ( @{$status} )\n"; }

    ...produces...

    Temp: ( CPU Temp = 30, GFX Temp = 45, RAM Temp = 40 ) Status: ( CPU Status = OK, GFX Status = OK, RAM Status = OK )

    If you're reading these in from a file, you don't really need to hold the original list in an array. You can just push onto @temp until a blank (or all space) line is reached, and then start pushing onto @status. But your question stated the data is already in an array, so my code will handle that well.


    Dave

Re: Using the map function
by AnomalousMonk (Abbot) on Jul 11, 2013 at 00:34 UTC

    I really like 2teez hash approach, although I would do it a little differently. Also a couple of array-only approaches. All of these easily generalize to any number of output arrays/groups/whatever. Note that the approach based on List::MoreUtils::part leaves you with a sub-array 0 filled with delimiter dreck.

    >perl -wMstrict -le "use List::MoreUtils qw(part); use Data::Dump; ;; my @ra = ( 'CPU Temp = 30', 'GFX Temp = 45', 'RAM Temp = 40', '', 'CPU Status = OK', 'GFX Status = OK', 'RAM Status = OK', ); ;; my $p = 1; my @parts = part { m{ \A \s* \z }xms ? ($p = 2, 0) : $p } @ra; dd \@parts; ;; my @pointer = \my (@ra_1, @ra_2); my $pp = 0; m{ \A \s* \z }xms ? $pp = 1 : push @{ $pointer[$pp] }, $_ for @ra; dd \@ra_1; dd \@ra_2; ;; my %hash; m{ \b (Temp|Status) \b }xms and push @{ $hash{$1} }, $_ for @ra; dd \%hash; " [ [""], ["CPU Temp = 30", "GFX Temp = 45", "RAM Temp = 40"], ["CPU Status = OK", "GFX Status = OK", "RAM Status = OK"], ] ["CPU Temp = 30", "GFX Temp = 45", "RAM Temp = 40"] ["CPU Status = OK", "GFX Status = OK", "RAM Status = OK"] { Status => ["CPU Status = OK", "GFX Status = OK", "RAM Status = OK"], Temp => ["CPU Temp = 30", "GFX Temp = 45", "RAM Temp = 40"], }
Re: Using the map function
by NetWallah (Abbot) on Jul 11, 2013 at 14:43 UTC
    A variation on johngg's approach - IMHO - easier to read, and it does use 'map', albiet probably not how the OP intended:
    #!/usr/bin/perl use strict; use warnings; use Data::Dumper; #Get the data into a scalar. my $content = do {local $/=undef;<DATA>}; # Slurp local $/="\n\n"; open my $f, "<", \$content or die "Cannot open scalar:$!"; my (@temps, @status); while (<$f>) { # We get all 3 items on a line my @row = m/(\w+)/g; if ($row[1] eq "Temp"){ push @temps, {map {$row[$_*3 - 3] => $row[$_*3 - 1]} 1..3}; }else{ push @status, {map {$row[$_*3 - 3] => $row[$_*3 - 1]} 1..3}; } } print Dumper \@temps, \@status; __DATA__ CPU Temp = 30 GFX Temp = 45 RAM Temp = 40 CPU Status = OK GFX Status = OK RAM Status = OK
    Output:
    $VAR1 = [ { 'GFX' => '45', 'RAM' => '40', 'CPU' => '30' } ]; $VAR2 = [ { 'GFX' => 'OK', 'RAM' => 'OK', 'CPU' => 'OK' } ];
    Of course, the whole 'read into a scalar' thing could be avoided if we were doing io on a 'real' file.

                 My goal ... to kill off the slow brain cells that are holding me back from synergizing my knowledge of vertically integrated mobile platforms in local cloud-based content management system datafication.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1043506]
Approved by frozenwithjoy
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (6)
As of 2014-12-28 14:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (181 votes), past polls