Re: Using the map function
by MidLifeXis (Monsignor) 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.
| [reply] [d/l] [select] |
Re: Using the map function
by frozenwithjoy (Priest) on Jul 10, 2013 at 17:41 UTC
|
#!/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
| [reply] [d/l] [select] |
Re: Using the map function
by 2teez (Vicar) 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
| [reply] [d/l] [select] |
Re: Using the map function
by davido (Cardinal) 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.
| [reply] [d/l] [select] |
Re: Using the map function
by AnomalousMonk (Archbishop) 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"],
}
| [reply] [d/l] [select] |
Re: Using the map function
by johngg (Canon) 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.
| [reply] [d/l] |
Re: Using the map function
by Skeeve (Parson) 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
| [reply] [d/l] [select] |
Re: Using the map function
by NetWallah (Canon) 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.
| [reply] [d/l] [select] |