in reply to Is it Perl "join" that can help me?
use 5.010; use strict; use File::Temp (); use Path::Class (); my $temp = Path::Class::Dir->new( File::Temp::tempdir() ); my $file1 = $temp->file('file1.txt'); my $file2 = $temp->file('file2.txt'); # Create files to operate on. # You already have these files, so you don't need to make them. print { $file1->openw } <<DATA; pizza pickle omellete coke blackforest croissant DATA # (note: following includes tabs - beware if # copying and pasting from PerlMonks!) print { $file2->openw } <<DATA; salt pizza 1 salt pickle 1 pepper omelette 1 pepper pickle 1 sugar coke 1 DATA # OK, now let's start the real work... # List of all meals my @meals = $file1->slurp(chomp => 1); # This will help us generate a list of all ingredients. my %ingredients; # Record pairings between ingredients and meals my %pairings; # Loop through file2 building up previous hashes. for ($file2->slurp(chomp => 1)) { my ($ing, $meal, $bool) = split /\t/; $ingredients{$ing} = 1; # record that the ingredient exist +s at all $pairings{$ing, $meal} = $bool; # record the pairing of ingredient + and meal } # List of all ingredients my @ingredients = keys %ingredients; # For each pair of ingredient and meal... for my $i (sort @ingredients) { for my $m (sort @meals) { printf( "%s\t%s\t%d\n", # format string $i, # ingredient $m, # meal $pairings{$i, $m}, # paired? ); # Note that $pairings{$i, $m} is # converted to an integer by printf # because of the '%d' formatting # code. Thus if there's no pairing, # we get '0'. } } # Clean up temp dir $temp->rmtree;
An alternative way of writing the output loop would be to use List::MapMulti, in which case it would be:
my $pairs = iterator_multi(\@ingredients, \@meals); while (my ($i, $m) = $pairs->()) { printf("%s\t%s\t%d\n", $i, $m, !!$pairings{$i, $m}); }
Or even:
say for mapm { join "\t", @_, 0+ $pairings{$_[0], $_[1]} } \@ingredien +ts, \@meals;
|
|---|