PrePAN

Sign in to PrePAN

List::GroupBy Group a list of hashref's to a multilevel hash of hashrefs of arrayrefs

Good

Synopsis

use List::GroupBy qw( groupBy );

my @list = (
    { firstname => 'Fred',   surname => 'Blogs', age => 20 },
    { firstname => 'George', surname => 'Blogs', age => 30 },
    { firstname => 'Fred',   surname => 'Blogs', age => 65 },
    { firstname => 'George', surname => 'Smith', age => 32 },
    { age => 99 },
);

my %groupedList = groupBy ( [ 'surname', 'firstname' ], @list );

# %groupedList => (
#     'Blogs' => {
#         'Fred' => [
#             { firstname => 'Fred',   surname => 'Blogs', age => 20 },
#             { firstname => 'Fred',   surname => 'Blogs', age => 65 },
#         ],
#         'George' => [
#             { firstname => 'George', surname => 'Blogs', age => 30 },
#         ],
#     },
#     'Smith' => {
#         'George' => [
#             { firstname => 'George', surname => 'Smith', age => 32 },
#         ],
#     },
#     '' => {
#         '' => [
#             { age => 99 },
#         },
#     },
# )


%groupedList = groupBy(
    {
        keys => [ 'surname', 'firstname' ],
        defaults => { surname => 'blogs' }
    },
    @list
);

# %groupedList => (
#     Blogs => {
#         Fred => [
#             { firstname => 'Fred',   surname => 'Blogs', age => 20 },
#             { firstname => 'Fred',   surname => 'Blogs', age => 65 },
#         ],
#         George => [
#             { firstname => 'George', surname => 'Blogs', age => 30 },
#         ],
#         '' => [
#             { age => 99 },
#         ],
#     },
#     Smith => {
#         George => [
#             { firstname => 'George', surname => 'Smith', age => 32 },
#         ],
#     },
# )


%groupedList = groupBy (
    {
        keys => [ 'surname', 'firstname' ],
        defaults => { surname => 'Blogs' },
        operations => { surname => sub { uc $_[0] } },
    },
    @list
);

# %groupedList => (
#     BLOGS => {
#         Fred => [
#             { firstname => 'Fred',   surname => 'Blogs', age => 20 },
#             { firstname => 'Fred',   surname => 'Blogs', age => 65 },
#         ],
#         George => [
#             { firstname => 'George', surname => 'Blogs', age => 30 },
#         ],
#         '' => [
#             { age => 99 },
#         ],
#     },
#     SMITH => {
#         George => [
#             { firstname => 'George', surname => 'Smith', age => 32 },
#         ],
#     },
# )

Description

List::GroupBy provides functions to group a list of hashrefs in to a hash of hashrefs of arrayrefs.

FUNCTIONS

  • groupBy( [ 'primary key', 'secondary key', ... ], LIST )

    If called with and array ref as the first parameter then groupBy will group the list by the keys provided in the array ref.

    Note: undefined values for a key will be defaulted to the empty string.

    Returns a hash of hashrefs of arrayrefs

  • groupBy( { keys => [ 'key', ... ], defaults => { 'key' => 'default', ... }, operations => { 'key' => sub, ... }, LIST )

    More advanced options are available by calling groupBy with a hash ref of options as the first parameter. Available options are:

    • keys (Required)

      An array ref of the keys to use for grouping. The order of the keys dictates the order of the grouping. So the first key is the primary grouping, the second key is used for the secondary grouping under the primary grouping an so on.

    • defaults (Optional)

      A hash ref of defaults to use one or more keys. If a key for an item is undefined and there's an entry in the defaults option then that will be used. If no default value has been supplied for a key then the empty string will be used.

    • operations (Optional)

      A hash ref mapping keys to a function to use to normalise value's when grouping. If there's no entry for a key then the value is just used as is.

      Each funtion is passed the value as it's only parameter and it's return value is used for the key.

    Returns a hash of hashrefs of arrayrefs

Comments

anonymouse
Anonymous
Can't List::Pairwise and the pair* functions in List::Util accomplish something similar?
Honestly I can't see an easy way to use the pair/pairwise functions to convert an array of hashrefs into a multi-level hash of hashrefs. For just one level you can use List::Util's reduce function, but for multiple levels of grouping it gets messy.
You might join both functions into one, permitting further extensions:

groupBy({keys => [qw(surname firstname)]}, @list);

groupBy({keys => [qw(surname firstname)], defaults => {surname => 'blogs'}}, @list);
Good idea, I've changed the interface based on this.

Please sign up to post a review.