For Programmers: Free Programming Magazines  


Home > Archive > PERL Miscellaneous > March 2004 > Variable substitution in variable name









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]

 

Author Variable substitution in variable name
mshetty

2004-03-30, 9:47 am

Hi,

Have the following code where I want to reduce the lines of code:

#Variables to store total file count for each type
$total_cpp_file=0;
$total_h_file=0;
$total_c_file=0;
$total_inp_file=0;
$total_inl_file=0;
$total_hpp_file=0;
$total_cc_file=0;
$total_hh_file=0;
$total_yxx_file=0;
$total_y_file=0;
$total_l_file=0;

find (\&wanted, "S:\\src");
find (\&wanted, "S:\\inc");
sub wanted
{
store_file ($File::Find::name);
}

sub store_file ($)
{
my $name = shift;
if ($name =~ /\.(cpp)$/i)
{
$total_cpp_file++;
push @files_cpp, ($name);
}
elsif ($name =~ /\.(h)$/i)
{
$total_h_file++;
push @files_h, ($name);
}
elsif ($name =~ /\.(c)$/i)
{
$total_c_file++;
push @files_c, ($name);
}
elsif ($name =~ /\.(inp)$/i)
{
$total_inp_file++;
push @files_INP, ($name);
}
elsif ($name =~ /\.(inl)$/i)
{
$total_inl_file++;
push @files_INL, ($name);
}
elsif ($name =~ /\.(hpp)$/i)
{
$total_hpp_file++;
push @files_HPP, ($name);
}
elsif ($name =~ /\.(cc)$/i)
{
$total_cc_file++;
push @files_CC, ($name);
}
elsif ($name =~ /\.(hh)$/i)
{
$total_hh_file++;
push @files_HH, ($name);
}
elsif ($name =~ /\.(yxx)$/i)
{
$total_yxx_file++;
push @files_YXX, ($name);
}
elsif ($name =~ /\.(y)$/i)
{
$total_y_file++;
push @files_Y, ($name);
}
elsif ($name =~ /\.(l)$/i)
{
$total_y_file++;
push @files_L, ($name);
}elsif ($name =~ /\.(dsp)$/i)
{
push @files_dsp, ($name);
}

} #store_file end

IS there a shorter way to write this?

I mean can I store (cpp, h, c, inp, inl, hpp, cc, hh, yxx, y, l) in an
array(file_type and say push @files_$file_type[1]?

Thanks and Regards,
M Shetty
A. Sinan Unur

2004-03-30, 9:47 am

mshetty@mail.com (mshetty) wrote in
news:bfbb8fd4.0403300558.6f63967c@posting.google.com:

> Hi,
>
> Have the following code where I want to reduce the lines of code:
>
> #Variables to store total file count for each type


OK ...

snipped a bunch of lines of noise

> IS there a shorter way to write this?


Use a hash.

my %totals = (
cpp => 0,
hpp => 0
ini => 0,
# ... etc etc
);

print 'Total for cpp: ', $totals{ini}, "\n";

--
A. Sinan Unur
1usa@llenroc.ude (reverse each component for email address)
Gunnar Hjalmarsson

2004-03-30, 10:44 am

mshetty wrote:
> Have the following code where I want to reduce the lines of
> code:
>
> #Variables to store total file count for each type
> $total_cpp_file=0;
> $total_h_file=0;


<snip>

Learn about scoping, and enable strictures.

> if ($name =~ /\.(cpp)$/i)
> {
> $total_cpp_file++;
> push @files_cpp, ($name);
> }


<snip>

> IS there a shorter way to write this?


Absolutely.

The counters should better be hash elements.

my %total;

A hash for storing the file names would also be suitable:

my %files;

Instead of all the if-elsif-else statements, you could do something like:

if ($name =~ /\.(\w+)$/) {
$total{$1}++;
push @{ $files{$1} }, $name;
}

That would make %files a hash of arrays.

HTH

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl

Paul Lalli

2004-03-30, 10:44 am

On Tue, 30 Mar 2004, mshetty wrote:

>
> Hi,
>
> Have the following code where I want to reduce the lines of code:
>
> #Variables to store total file count for each type
> $total_cpp_file=0;
> $total_h_file=0;
> $total_c_file=0;
> $total_inp_file=0;
> $total_inl_file=0;
> $total_hpp_file=0;
> $total_cc_file=0;
> $total_hh_file=0;
> $total_yxx_file=0;
> $total_y_file=0;
> $total_l_file=0;
>
> find (\&wanted, "S:\\src");
> find (\&wanted, "S:\\inc");
> sub wanted
> {
> store_file ($File::Find::name);
> }
>
> sub store_file ($)
> {
> my $name = shift;
> if ($name =~ /\.(cpp)$/i)
> {
> $total_cpp_file++;
> push @files_cpp, ($name);
> }


<etc>

> IS there a shorter way to write this?
>
> I mean can I store (cpp, h, c, inp, inl, hpp, cc, hh, yxx, y, l) in an
> array(file_type and say push @files_$file_type[1]?
>
> Thanks and Regards,
> M Shetty
>



Use a hash of arrays.

my %files;

sub store_file {
my $name = shift;
if ($name =~ /\.(.*)$/i)){
push @{$files{$1}}, $name;
} else {
warn "Unknown file type: $name\n";
}
}

sub print_files {
foreach (keys %files){
local $, = ", ";
print "There are " . @{$files{$_}} . " $_ files:\n";
print @{$files{$_}};
}
}

HTH,
Paul Lalli
Web Surfer

2004-03-30, 11:43 am

[This followup was posted to comp.lang.perl.misc]

In article <bfbb8fd4.0403300558.6f63967c@posting.google.com>,
mshetty@mail.com says...
> Hi,
>
> Have the following code where I want to reduce the lines of code:
>
> #Variables to store total file count for each type
> $total_cpp_file=0;
> $total_h_file=0;
> $total_c_file=0;
> $total_inp_file=0;
> $total_inl_file=0;
> $total_hpp_file=0;
> $total_cc_file=0;
> $total_hh_file=0;
> $total_yxx_file=0;
> $total_y_file=0;
> $total_l_file=0;
>
> find (\&wanted, "S:\\src");
> find (\&wanted, "S:\\inc");
> sub wanted
> {
> store_file ($File::Find::name);
> }
>
> sub store_file ($)
> {
> my $name = shift;
> if ($name =~ /\.(cpp)$/i)
> {
> $total_cpp_file++;
> push @files_cpp, ($name);
> }
> elsif ($name =~ /\.(h)$/i)
> {
> $total_h_file++;
> push @files_h, ($name);
> }
> elsif ($name =~ /\.(c)$/i)
> {
> $total_c_file++;
> push @files_c, ($name);
> }
> elsif ($name =~ /\.(inp)$/i)
> {
> $total_inp_file++;
> push @files_INP, ($name);
> }
> elsif ($name =~ /\.(inl)$/i)
> {
> $total_inl_file++;



You could use a hash.

my %totals = ( "cpp" => 0 , "h" => 0 , "c" => 0 );
# of course you will need to code the entries for ALL possible filename
# extensions

To increment an element :

$totals{"cpp"} += 1;
Anno Siegel

2004-03-30, 11:43 am

Gunnar Hjalmarsson <noreply@gunnar.cc> wrote in comp.lang.perl.misc:
> mshetty wrote:

[...]
[color=darkred]
> Instead of all the if-elsif-else statements, you could do something like:
>
> if ($name =~ /\.(\w+)$/) {
> $total{$1}++;
> push @{ $files{$1} }, $name;
> }


The %total hash is not needed any more. The count can be read off the
arrays:

my $total = @{ $files{ $key}}

Anno

Gunnar Hjalmarsson

2004-03-30, 12:39 pm

Web Surfer wrote:
> You could use a hash.


Agreed.

> my %totals = ( "cpp" => 0 , "h" => 0 , "c" => 0 );
> # of course you will need to code the entries for ALL possible
> # filename extensions


No. Please read the rest of the thread before posting your advice.

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl

John W. Krahn

2004-03-30, 6:36 pm

mshetty wrote:
>
> Hi,
>
> Have the following code where I want to reduce the lines of code:
>
> #Variables to store total file count for each type
> $total_cpp_file=0;
> $total_h_file=0;
> $total_c_file=0;
> $total_inp_file=0;
> $total_inl_file=0;
> $total_hpp_file=0;
> $total_cc_file=0;
> $total_hh_file=0;
> $total_yxx_file=0;
> $total_y_file=0;
> $total_l_file=0;
>
> find (\&wanted, "S:\\src");
> find (\&wanted, "S:\\inc");
> sub wanted
> {
> store_file ($File::Find::name);
> }
>
> sub store_file ($)
> {
> my $name = shift;
> if ($name =~ /\.(cpp)$/i)
> {
> $total_cpp_file++;
> push @files_cpp, ($name);
> }
> elsif ($name =~ /\.(h)$/i)
> {
> $total_h_file++;
> push @files_h, ($name);
> }
> elsif ($name =~ /\.(c)$/i)
> {
> $total_c_file++;
> push @files_c, ($name);
> }
> elsif ($name =~ /\.(inp)$/i)
> {
> $total_inp_file++;
> push @files_INP, ($name);
> }
> elsif ($name =~ /\.(inl)$/i)
> {
> $total_inl_file++;
> push @files_INL, ($name);
> }
> elsif ($name =~ /\.(hpp)$/i)
> {
> $total_hpp_file++;
> push @files_HPP, ($name);
> }
> elsif ($name =~ /\.(cc)$/i)
> {
> $total_cc_file++;
> push @files_CC, ($name);
> }
> elsif ($name =~ /\.(hh)$/i)
> {
> $total_hh_file++;
> push @files_HH, ($name);
> }
> elsif ($name =~ /\.(yxx)$/i)
> {
> $total_yxx_file++;
> push @files_YXX, ($name);
> }
> elsif ($name =~ /\.(y)$/i)
> {
> $total_y_file++;
> push @files_Y, ($name);
> }
> elsif ($name =~ /\.(l)$/i)
> {
> $total_y_file++;
> push @files_L, ($name);
> }elsif ($name =~ /\.(dsp)$/i)
> {
> push @files_dsp, ($name);
> }
>
> } #store_file end
>
> IS there a shorter way to write this?
>
> I mean can I store (cpp, h, c, inp, inl, hpp, cc, hh, yxx, y, l) in an
> array(file_type and say push @files_$file_type[1]?


Yes there is a shorter way:

use warnings;
use strict;
use File::Find;

my @types = qw( cpp hpp inp inl yxx cc hh c h l y );
# types must have longest first to work correctly
my $regex = qr/@{[ join '|', @types ]}/i;

my %totals;
find( sub{
return unless /\.($regex)$/;
push @{ $totals{ $1 } }, $File::Find::name;
}, 'S:/src', 'S:/inc' );

print <<HEADER;
Type Count
----------
HEADER
for my $type ( sort keys %totals ) {
printf "%4s %d\n", $type, @{ $totals{ $type } };
}

__END__



John
--
use Perl;
program
fulfillment
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com