Thank you very much, Corion .
I did think about a loop but it seems that I needed that the pope gives me a kick :-) I must admit however that I could not wrap my head around the flag $changed yet. Could you please give me another hint on this? Below is my new attempt with the do ... while loop. I updated the sample data to see that the longer chain will be proceeded.
!/perl
use strict;
use warnings FATAL => qw(all);
use Text::CSV_XS;
use Data::Dump;
my $csv_par =
{
binary => 1, auto_diag => 1, allow_whitespace => 1,
sep_char => ';', eol => $/, quote_char => undef,
};
my $csv = Text::CSV_XS->new($csv_par);
my @data = @{ $csv->getline_all(*DATA) };
shift @data; # simply throw away the header.
my %main;
my %hash_old;
############### The first pass:
for my $row ( @data )
{
$hash_old{$row->[0]} = $row->[1];
$main{$row->[0]} = $row->[1];
}
my %hash_new;
############### All the remaining steps:
do
{
for my $row (@data)
{
if ( $hash_old{$row->[1]} )
{
$hash_new{$row->[0]} = $row->[1];
$main{ $row->[0] } =
$main{ $row->[1] } || $row->[1];
}
}
%hash_old = ();
$hash_old{$_} = $hash_new{$_} for keys %hash_new;
%hash_new = ();
}
while ( scalar keys %hash_old );
############### Filling in the main number
############### for the main number themselves:
for my $row ( @data )
{
$main{$row->[1]} = $row->[1]
unless exists $main{$row->[1]} or $row->[1] eq "";
$main{$row->[0]} = $row->[0]
unless length($main{$row->[0]});
}
# Sample chains:
# 123-234-345-456-567-678-789
# 117-228-339
# 131
# 213-324-435
# 372
dd \%main;
The output now:
{
117 => 117,
123 => 123,
131 => 131,
213 => 213,
228 => 117,
234 => 123,
324 => 213,
339 => 117,
345 => 123,
372 => 372,
435 => 213,
456 => 123,
567 => 123,
678 => 123,
789 => 123,
}