Home > Archive > PERL Programming > October 2005 > Better code
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
| George Bouras 2005-10-05, 6:56 pm |
| The following work just fine, but I did not like the duplicated lines.
open(FILE1, "<$file1");
open(FILE2, "<$file2");
while(<FILE1> ) { chomp; next if /^\s*$/; s/\s*(.*)\s*/\1/; @list1{ split(
/\s*,\s*/ ,$_) } = 1 }
while(<FILE2> ) { chomp; next if /^\s*$/; s/\s*(.*)\s*/\1/; @list2{ split(
/\s*,\s*/ ,$_) } = 1 }
close FILE1;
close FILE2;
map { $list1_nocase{ lc $_ } = 1 } keys %list1;
map { $list2_nocase{ lc $_ } = 1 } keys %list2;
So I used a for. At the loop you can handle the values but
not the names of the data holders like arrays, variables,
hashes ... so I used the eval statements. The loop code also
works ok but again I do not like the eval statements because they
are slow and ugly. The question is how to make the initial
code unique without the "eval" ? with glob references maybe ?
If the similar pieces was 100 the problem would be bigger.
for my $i (1,2)
{
my $file = eval "\$file$i";
local *FILE = \"FILE$i";
open(FILE, "<$file");
while(<FILE> ) { chomp; next if /^\s*$/; s/\s*(.*)\s*/\1/; eval "\@list$i\{
split( /\\s*,\\s*/ ,\$_ ) \} = 1" }
close FILE;
eval "map { \$list$i_nocase{ lc \$_ } = 1 } keys \%list$1";
$}
| |
| Paul Lalli 2005-10-05, 6:56 pm |
| George Bouras wrote:
> The following work just fine, but I did not like the duplicated lines.
>
> open(FILE1, "<$file1");
> open(FILE2, "<$file2");
> while(<FILE1> ) { chomp; next if /^\s*$/; s/\s*(.*)\s*/\1/; @list1{ split(
> /\s*,\s*/ ,$_) } = 1 }
> while(<FILE2> ) { chomp; next if /^\s*$/; s/\s*(.*)\s*/\1/; @list2{ split(
> /\s*,\s*/ ,$_) } = 1 }
> close FILE1;
> close FILE2;
> map { $list1_nocase{ lc $_ } = 1 } keys %list1;
> map { $list2_nocase{ lc $_ } = 1 } keys %list2;
>
>
> So I used a for. At the loop you can handle the values but
> not the names of the data holders like arrays, variables,
> hashes ... so I used the eval statements. The loop code also
> works ok but again I do not like the eval statements because they
> are slow and ugly. The question is how to make the initial
> code unique without the "eval" ? with glob references maybe ?
> If the similar pieces was 100 the problem would be bigger.
>
>
> for my $i (1,2)
> {
> my $file = eval "\$file$i";
> local *FILE = \"FILE$i";
> open(FILE, "<$file");
> while(<FILE> ) { chomp; next if /^\s*$/; s/\s*(.*)\s*/\1/; eval "\@list$i\{
> split( /\\s*,\\s*/ ,\$_ ) \} = 1" }
> close FILE;
> eval "map { \$list$i_nocase{ lc \$_ } = 1 } keys \%list$1";
> $}
Why not just make subroutines? And why not use lexical filehandle
references instead of messing with global typeglobs? And why not use
real hashes and arrays rather than messing with evals and symrefs?
[UNTESTED]
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
sub read_file {
my $filename = shift;
my %list;
open my $fh, '<', $filename or die "Cannot open $filename: $!\n";
while (<$fh> ){
chomp;
next if /^\s*$/;
s/^\s+//;
s/\s+$//; #more efficient than the combined statement
@list{split /\s*,\s*/, $_} = 1;
}
return \%list;
}
my (@lists, @lists_no_case);
foreach my $file ('FILE1', 'FILE2'){
my $list_ref = read_file($file);
my %list_no_case = map { lc $_ => 1 } keys %list_ref;
push @lists, $list_ref;
push @lists_no_case, \%list_no_case;
}
print Dumper(\@lists, \@lists_no_case);
__END__
Paul Lalli
| |
| John W. Krahn 2005-10-05, 6:56 pm |
| George Bouras wrote:
> The following work just fine, but I did not like the duplicated lines.
>
> open(FILE1, "<$file1");
> open(FILE2, "<$file2");
> while(<FILE1> ) { chomp; next if /^\s*$/; s/\s*(.*)\s*/\1/; @list1{ split(
> /\s*,\s*/ ,$_) } = 1 }
> while(<FILE2> ) { chomp; next if /^\s*$/; s/\s*(.*)\s*/\1/; @list2{ split(
> /\s*,\s*/ ,$_) } = 1 }
> close FILE1;
> close FILE2;
> map { $list1_nocase{ lc $_ } = 1 } keys %list1;
> map { $list2_nocase{ lc $_ } = 1 } keys %list2;
>
>
> So I used a for. At the loop you can handle the values but
> not the names of the data holders like arrays, variables,
> hashes ... so I used the eval statements. The loop code also
> works ok but again I do not like the eval statements because they
> are slow and ugly. The question is how to make the initial
> code unique without the "eval" ?
local @ARGV = ( $file1, $file2 );
my $key = 'list1';
my %data;
while ( <> ) {
$key = 'list2' if eof;
next unless /\S/;
my @fields = map { s/\A\s+//; s/\s+\z//; $_ } split /,/;
@{ $data{ $key } }{ @fields } = ();
@{ $data{ "${key}_nocase" } }{ map lc, @fields } = ();
}
John
--
use Perl;
program
fulfillment
|
|
|
|
|