http://qs321.pair.com?node_id=1096847

vagabonding electron has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

I have a table which has two columns: the number and the previous number. There can be more than two items in the chain. I build a hash where the key is the number and the value is the very first item in the chain.

Below is my code by now (a minimal example to play with). It just works, but it is fragile, since it relies on the assumption that there is at most 5 items in the chain. In the real task it should be so, but it is not guaranteed. What would be the better way to do it?

Thanks in advance!

#!/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 %first_pass; for my $row ( @data ) { $first_pass{$row->[0]} = $row->[1]; $main{$row->[0]} = $row->[1]; } my %second_pass; for my $row (@data) { if ( $first_pass{$row->[1]} ) { $second_pass{$row->[0]} = $row->[1]; $main{ $row->[0] } = $main{ $row->[1] } || $row->[1]; } } my %third_pass; for my $row (@data) { if ( $second_pass{$row->[1]} ) { $third_pass{$row->[0]} = $row->[1]; $main{ $row->[0] } = $main{ $row->[1] } || $row->[1]; } } my %fourth_pass; for my $row (@data) { if ( $third_pass{$row->[1]} ) { $fourth_pass{$row->[0]} = $row->[1]; $main{ $row->[0] } = $main{ $row->[1] } || $row->[1]; } } for my $row ( @data ) { $main{$row->[1]} = "" unless exists $main{$row->[1]} or $row->[1] eq ""; } for my $num ( sort {$a <=> $b} keys %main ) { $main{$num} = $num unless length($main{$num}); print "$num => $main{$num}$/"; } # Sample chains: # 123-234-345-456-567 # 117-228-339 # 131 # 213-324-435 # 372 __DATA__ NUM;NUMPRED 567;456 456;345 345;234 234;123 339;228 228;117 131; 435;324 324;213 372;
The output:
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