Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
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 taking refuge in the Monastery: (7)
As of 2014-09-16 12:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (15 votes), past polls