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
AUTHOR
Simone Cesano <scesano@cpan.org>
COPYRIGHT AND LICENSE
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.