in reply to Sort the hash array

You're not storing $timereceived as part of the array. If you did store it like this:

push @$records, { timereceived => $dtevent, ...

then after the loop you could do this:

@$records = sort { $a->{timereceived} <=> $b->{timereceived} } @$recor +ds;

because DateTime objects overload the numeric comparison operators. BTW, there does not appear to be a need for the array reference $records in your code, you could just use a plain array my @records.

Update: See also sort and How do I sort an array by (anything)?

Replies are listed 'Best First'.
Re^2: Sort the hash array
by snehit.ar (Beadle) on Jul 06, 2017 at 10:56 UTC
    Thank you sir .. I am beginner to perl ,so if you could help to optimized my code with perform below step :: 1. Read the XML file 2. get required nodes using for loop 3. Need to sort this data 4. store the sorted data in array 5. Convert the hash array to JSON 6. Push Json data to httprequest. i will be great help if you can correct where ever in code,I'm missing basic perl syntax and line not relevant..
      I am beginner to perl ,so if you could help to optimized my code with perform below step ... i will be great help if you can correct where ever in code,I'm missing basic perl syntax and line not relevant..

      For a beginner, your code looks pretty good, and there are no syntax errors in it (including the commented out code). Are you having problems with it? If so, feel free use the resources of PerlMonks, e.g. Basic debugging checklist and How do I post a question effectively?

      Because the code depends on XML input and servers I don't have available to me, I can't run it, but from a quick read-through I have the following suggestions for improvements:

      • The first line should be #!/usr/bin/perl (or perhaps #!/usr/bin/env perl to use whatever Perl is in the PATH).
      • You don't need both use JSON; and use Cpanel::JSON::XS qw(encode_json);, I think the latter is enough.
      • I don't think you need use DateTime::Duration; or use DateTime::Format::Duration;.
      • As I said, I would suggest you replace my $records = []; with my @records, and then every @$records with @records.
      • You don't seem to be using $count.
      • You do this several times: $var =~ s/\n//; which will remove the first newline character from the string. It's also possible that the XML data might change in the future, so I might recommend the following, more flexible regex, which will trim all whitespace from the beginning and end of the string: s/^\s+|\s+$//g
      • Don't reformat $timereceived with regexes, just adjust the strptime pattern accordingly: '%Y-%m-%dT%H:%M:%S.%3NZ'
      • I suggest you move my $dtnow = DateTime->now; before the loop.
      • This code doesn't match the comment: if ($diff_hours>2000) { # Get the event details which are more then 2 hours
      • While you're free to use a module like Math::Round if you need precise control, note that Perl's sprintf will also do basic rounding for you: sprintf("%.0f h", $diff_hours);
        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";