Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re: Get most recent data based on a date from an array of hashes.

by davido (Cardinal)
on Jan 18, 2022 at 20:54 UTC ( [id://11140585]=note: print w/replies, xml ) Need Help??


in reply to Get most recent data based on a date from an array of hashes.

I would approach it by transforming the date field into ISO8601 format, holding onto it as a sort key, and then sorting based on that format. Here's one way of doing that:

use strict; use warnings; use Data::Dumper; my $data = [ { 'Color' => 'green', 'Step' => 'Platform', 'acc' => '1111', 'Date' => '08-06-2022' }, { 'Color' => 'black', 'Step' => 'Platform', 'acc' => '1111', 'Date' => '01-05-2019' }, { 'Color' => 'blue', 'Step' => 'Platform', 'acc' => '1111', 'Date' => '10-11-2020' }, { 'Color' => 'white', 'Step' => 'Platform', 'acc' => '1111', 'Date' => '01-03-2022' }, { 'Color' => 'red', 'Step' => 'Platform', 'acc' => '1111', 'Date' => '03-21-2021' }, ]; my @sorted = map { $_->[1] } # Drop the date key + keeping only the payload sort { $a->[0] cmp $b->[0] } # Sort based on dat +e key map { [to_iso8601($_->{Date}), $_] } # Temporarily store + tuples of transformed date key, payload @$data; print Dumper \@sorted; sub to_iso8601 { my $date = shift; # Extract the components of a mm-dd-yyyy format my %components; @components{qw(month day year)} = split /-/, $date; # Enforce month and date must be 2 digits, possibly adding a leadi +ng 0. $components{$_} =~ s/^(\d{1})$/0$1/ for qw(day month); # Return them as a string with the components rearranged as yyyy-m +m-dd # (ISO8601) return join '-', @components{qw(year month day)}; }

My own paranoia about date manipulation is that I should be using a module for date comparisons and transformations, so this approach sort of goes against my own instinct to not try to do date manipulation myself. If there's any possibility at all that dates aren't as easy to transform as I've done here, use a module for that.

This approach uses a Schwartzian Transform to augment the data we're sorting with a sort key. We create a tuple of [$sort_key, $payload], sort those tuples, then retain only the payload from the sorted tuples. And this approach defines a to_iso8601 function that converts mm-dd-yyyy format (or even m-d-yyyy) to yyyy-mm-dd format to use as a sort key.


Dave

Replies are listed 'Best First'.
Re^2: Get most recent data based on a date from an array of hashes.
by cavac (Parson) on Jan 20, 2022 at 09:47 UTC

    Technically, if you only need to transform the date into a sortable key, you can just fudge the maths behind it to make it faster.

    Say, the original date is MM-DD-YYYY (one of the most useless date formats available to modern computing), you could do something like this:

    my $timestamp = '03-21-2021'; my ($month, $day, $year) = split/\-/, $timestamp; my $sortkey = $day + ($month * 100) + $year * 10000;

    Now that the thing is an integer, you can compare numerically, which is faster than a string compare.

    perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11140585]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2024-04-25 17:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found