#!/usr/bin/env perl use 5.010; use strict; use warnings; use List::Util qw{first}; use constant { HOUSE => 0, FAMILY => 1, EXTERN => 2, EXTRAS => 3 }; use constant INDEX => qw{HOUSE FAMILY EXTERN EXTRAS}; my @table; my %cross; while () { push @table, [ split ]; } say crosslink(HOUSE, FAMILY, 9); say crosslink(HOUSE, FAMILY, 9); say crosslink(FAMILY, HOUSE, 10); say crosslink(EXTRAS, EXTERN, '8text'); say crosslink(EXTRAS, FAMILY, '8text'); say crosslink(HOUSE, EXTRAS, 12); say crosslink(HOUSE, EXTRAS, 13); sub crosslink { my ($in, $out, $val) = @_; my $key = $in . '-' . $val; if (exists $cross{$key}) { return $cross{$key}[$out]; } say 'Search once only:'; # for testing only - remove in production my $found = first { $_->[$in] eq $val } @table; return 'Not found! ' . (INDEX)[$in] . ": $val" if ! defined $found; $cross{$key} = $found; return $cross{$key}[$out]; } __DATA__ 1 2 3 4text 5 6 7 8text 9 10 11 12text 13 14 15 16text #### $ pm_cross_table.pl Search once only: 10 10 Search once only: 9 Search once only: 7 6 Search once only: Not found! HOUSE: 12 Search once only: 16text