snehit.ar has asked for the wisdom of the Perl Monks concerning the following question:

I want to sort the array data based on the value of $timereceived . Also the output of array list is random ,list order of variable in array is not constant .
##!/usr/bin/perl use warnings; use strict; use XML::XPath; use Data::Dumper; use LWP::UserAgent; use JSON; use DateTime; use Math::Round; use DateTime::Duration; use DateTime::Format::Duration; 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 $records = []; my $json; my $count=0; # Counter to set the Line variable foreach my $node ($nodeset->get_nodelist) { my $severity = $xp->find('./severity', $node); $severity =~ s/\n//; # Remove prefix newline \n character my $ticketnum = $xp->find("./custom_attribute_list/custom_att +ribute[normalize-space(name)='SLB_RemedyIncident']/value", $node); $ticketnum=~ s/\n//; my $timereceived = $xp->find('./time_first_received', $node); $timereceived=~ s/\n//; my $service_name = $xp->find("./custom_attribute_list/custom_a +ttribute[normalize-space(name)='Service Name']/value", $node); $service_name=~ s/\n//; my $ssrid = $xp->find("./custom_attribute_list/custom_attribut +e[normalize-space(name)='SLB_SSRID']/value", $node); $ssrid=~ s/\n//; my $remedyqueue = $xp->find("./custom_attribute_list/custo +m_attribute[normalize-space(name)='SLB_RemedyQueue']/value", $node); $remedyqueue = [ map $_->string_value =~ s/\n//r, $remedyqueue +->get_nodelist ]; #Format Time received $timereceived =~ s/T/ /; #removing the T $timereceived =~ s/\.\d+Z//; #removing the Z #Calculate the time difference my $dtnow = DateTime->now; my $strp = DateTime::Format::Strptime->new(on_error=>'croak',p +attern => '%Y-%m-%d %H:%M:%S', 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 => round($diff_hours) . " h", } } } print Dumper(@$records); # Convert into JSON format $json = encode_json \@$records; # print $json; # my $uri = 'http://test/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: Sort the hash array
by haukex (Archbishop) on Jul 06, 2017 at 10:30 UTC

    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)?

      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);
Re: Sort the hash array
by Laurent_R (Canon) on Jul 06, 2017 at 10:29 UTC
    Hi snehit.ar,

    I'm not sure to understand what you want exactly, but if you wish to sort the content of the $record array ref based on the value of $timereceived, then you probably need to include the value of $timereceived as an additional field in your records.

    In addition, it would be nice if you showed a sample of your input data and of the output of the print Dumper statement. By the way,

    print Dumper $records;
    is likely to give you a more informative display than
    print Dumper @$records;
        Please put some <code> and </code> tags around both your XML input and your Dumper output.