Better code

Better code

am 05.10.2005 19:53:49 von George Bouras

The following work just fine, but I did not like the duplicated lines.

open(FILE1, "<$file1");
open(FILE2, "<$file2");
while() { chomp; next if /^\s*$/; s/\s*(.*)\s*/\1/; @list1{ split(
/\s*,\s*/ ,$_) } = 1 }
while() { 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() { 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";
$}

Re: Better code

am 05.10.2005 20:10:22 von Paul Lalli

George Bouras wrote:
> The following work just fine, but I did not like the duplicated lines.
>
> open(FILE1, "<$file1");
> open(FILE2, "<$file2");
> while() { chomp; next if /^\s*$/; s/\s*(.*)\s*/\1/; @list1{ split(
> /\s*,\s*/ ,$_) } = 1 }
> while() { 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() { 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

Re: Better code

am 05.10.2005 22:40:14 von someone

George Bouras wrote:
> The following work just fine, but I did not like the duplicated lines.
>
> open(FILE1, "<$file1");
> open(FILE2, "<$file2");
> while() { chomp; next if /^\s*$/; s/\s*(.*)\s*/\1/; @list1{ split(
> /\s*,\s*/ ,$_) } = 1 }
> while() { 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