NAME

Array::Join - performs SQL-like joins on arrays

SYNOPSIS

use Array::Join;

my @arr_a = (
    { id => 1, name => 'Alice' },
    { id => 2, name => 'Bob' },
);

my @arr_b = (
    { uid => 1, email => 'alice@example.com' },
    { uid => 3, email => 'carol@example.com' },
);

my @joined = join_arrays(
    \@arr_a,
    \@arr_b,
    sub { $_->{id} },
    sub { $_->{uid} },
    {
        type  => 'left',
        merge => [ 'a', 'b' ],
    }
);

# Result:
# (
#   { 'a.id' => 1, 'a.name' => 'Alice', 'b.uid' => 1, 'b.email' => 'alice@example.com' },
#   { 'a.id' => 2, 'a.name' => 'Bob' },  # No match in B
# )

DESCRIPTION

Array::Join provides SQL-style joining functionality on arrayrefs of hashrefs.

It supports the four common SQL join types (inner, left, right, outer) and provides options to control merging behavior.

FUNCTIONS

join_arrays

@result = join_arrays($arr_a, $arr_b, $key_sub_a, $key_sub_b, \%opts);

Performs a join between two arrayrefs of hashrefs, using two key extractor functions. Returns a list of joined results.

  • $arr_a, $arr_b

    Arrayrefs of hashrefs to join.

  • $key_sub_a, $key_sub_b

    Code references that return the join key for a given item in the array.

    sub { $_->{foo} }
  • \%opts (optional)

    A hashref of options to configure the join behavior.

Options

  • type

    The type of join to perform. One of:

    'inner' (default)

    Return only matching pairs (intersection of keys in both inputs).

    'left'

    Include all entries from the left side, and matching entries from the right side if any.

    'right'

    Include all entries from the right side, and matching entries from the left side if any.

    'outer'

    Include all keys present in either array (full outer join). Rows without matches are joined with undef.

  • merge

    Controls how the matched pairs are flattened into a single hash per output row.

    This can be:

    A CODEREF

    A sub that receives two hashrefs (left and right item) and returns a merged hashref.

    merge => sub {
        my ($left, $right) = @_;
        return { %$left, %$right };
    }
    An ARRAYREF

    An arrayref of two prefix strings to apply to the keys of each side. For example:

    merge => [ 'left', 'right' ]

    Would turn:

    { name => 'Alice' } and { email => 'a@example.com' }

    into:

    { 'left.name' => 'Alice', 'right.email' => 'a@example.com' }
    'LEFT_PRECEDENT' or 'RIGHT_PRECEDENT' or other Hash::Merge behaviors

    These use the Hash::Merge behaviors to merge the hashes. For example:

    merge => 'LEFT_PRECEDENT'

    will favor keys from the left hashref when they conflict.

    true value

    Any other true value will merge using Hash::Merge’s default behavior.

    false/undef

    If merge is not provided or false, the result will be a list of arrayrefs with two elements (left, right). For example:

    [ $item_from_a, $item_from_b ]

INTERNAL FUNCTIONS

These are not exported.

make_lookup($arrayref, $key_sub)

Creates a hashref mapping keys to arrayrefs of array indexes for faster lookup.

make_keys($lookup_a, $lookup_b, \%opts)

Generates the list of join keys to consider, depending on join type.

make_joined(...)

Assembles the actual matching row pairs based on the join keys.

flatten_result($arrayref_of_pairs, \%opts)

Converts pairs of hashrefs into merged single hashes, based on merge option.

cross_product($listref1, $listref2)

Creates the full cross-product (i.e., every combination of pairings) between two lists of indexes.

EXPORTS

Only one function is exported by default:

  • join_arrays

CAVEATS

This was built for convenience, not performance. It's never been tested for very large arrays

TODO

  • Test comparing behaviour with SQL

  • More tests

  • Joining more than 2 arrays

SEE ALSO

Hash::Merge

AUTHOR

Simone Cesano <scesano@cpan.org>

This software is copyright (c) 2025 by Simone Cesano.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.