in reply to Re^3: Sort the hash array
in thread Sort the hash array

Sir, I really appreciate your efforts to correct me. I have Incorporated all the suggestion in the code and worked fine. Few more query: --is there way i can use s/^\s+|\s+$//g only once for all the variables and not repetitively ? --if i use sprintf("%.0f h", $diff_hours); gives me err in sorting statement Argument "2158 h" isn't numeric in numeric comparison (<=>) at XPathSample.pl line 55.
#!/usr/bin/env perl use warnings; use strict; use XML::XPath; use Data::Dumper; use LWP::UserAgent; use DateTime; use DateTime::Format::Strptime; use Cpanel::JSON::XS qw(encode_json); my $xml = 'events.xml'; my $xp = XML::XPath->new(filename => $xml); my $nodeset = $xp->findnodes('//event'); my $json; my @records; my $count=0; # Counter to set the Line variable my $dtnow = DateTime->now; foreach my $node ($nodeset->get_nodelist) { my $severity = $xp->find('./severity', $node); $severity =~ s/^\s+|\s+$//g; # Remove prefix newline \n charac +ter my $ticketnum = $xp->find("./custom_attribute_list/custom_att +ribute[normalize-space(name)='SLB_RemedyIncident']/value", $node); $ticketnum=~ s/^\s+|\s+$//g; my $timereceived = $xp->find('./time_first_received', $node); $timereceived=~ s/^\s+|\s+$//g; my $service_name = $xp->find("./custom_attribute_list/custom_a +ttribute[normalize-space(name)='Service Name']/value", $node); $service_name=~ s/^\s+|\s+$//g; my $ssrid = $xp->find("./custom_attribute_list/custom_attribut +e[normalize-space(name)='SLB_SSRID']/value", $node); $ssrid=~ s/^\s+|\s+$//gs; my $remedyqueue = $xp->find("./custom_attribute_list/custom_at +tribute[normalize-space(name)='SLB_RemedyQueue']/value", $node); $remedyqueue = [ map $_->string_value =~ s/\n//r, $remedyqueue +->get_nodelist ]; #Calculate the time difference my $strp = DateTime::Format::Strptime->new(on_error=>'croak',p +attern => '%Y-%m-%dT%H:%M:%S.%3NZ', time_zone=>'UTC'); my $dtevent = $strp->parse_datetime($timereceived); my $diff_sec = $dtnow->subtract_datetime_absolute($dtevent)->i +n_units('seconds'); my $diff_hours = $diff_sec/(60*60); #print "$diff_sec s / $diff_hours h\n"; if ($diff_hours>2000) { # Get the event details which are more + then 2 hours $count ++; push @records, { line => $count, severity => $severity, ticketnum => $ticketnum, appname => $service_name . "(" . $ssrid . ")", remedy_queue => $remedyqueue, event_age => sprintf("%.0f", $diff_hours), } } @records = sort { $b->{event_age} <=> $a->{event_age} } @recor +ds; # sort the records in decending order of event_age } print Dumper @records; # Convert into JSON format $json = encode_json \@records; # print $json; my $uri = 'http://US1455EPC0674.dir.slb.com:12224/api/submit/3160 +9de09a484e20b9e3a6e5b502be66/dims/line/tags/availability'; my $jsondata = $json; my $req = HTTP::Request->new( 'POST', $uri ); $req->header( 'Content-Type' => 'application/json'); $req->content( $json ); my $lwp = LWP::UserAgent->new; $lwp->request( $req ); print "Data send to Dashboard";

Replies are listed 'Best First'.
Re^5: Sort the hash array (updated)
by haukex (Archbishop) on Jul 06, 2017 at 12:38 UTC
    is there way i can use s/^\s+|\s+$//g only once for all the variables
    s/^\s+|\s+$//g for $severity, $ticketnum, $timereceived, ...;

    Doesn't apply to $remedyqueue though, one way to make that a little bit more idiomatic might be:

    my $remedyqueue = [ map { $_->string_value=~s/^\s+|\s+$//gr } $xp->find("./custom_attribute_list/custom_attribute[normalize-space( +name)='SLB_RemedyQueue']/value", $node) ->get_nodelist ];

    Or, for Perl versions before 5.14: map { (my $x=$_->string_value)=~s/^\s+|\s+$//g; $x }

    if i use sprintf("%.0f h", $diff_hours); gives me err in sorting statement Argument "2158 h" isn't numeric

    You didn't implement the suggestion I showed, instead you're attempting to sort by the field event_age, which does contain strings like "2158 h", which are not plain numbers and therefore can't be compared by the numeric comparison operator <=> <update> cause warnings when you try to use the numeric comparison operator <=> to compare them. </update> I would suggest you implement the suggestion I showed, and if you don't want that field to show up in the JSON, then after the sorting you could do delete $_->{timereceived} for @records;. (While you could theoretically also remove the " h" from the event_age field and then sort that numerically, note that since you've rounded the value, I think you might find that the sorting will be unreliable for events that happened in the same hour.) Also, note that you should move the sort entirely outside the loop, doing it on every iteration is not necessary.