On Friday 04 Dec 2009 06:10:16 Eric Mooshagian wrote:
> Dear All,
> 
> This is my first post.
> 
> I present some subroutines that  1) create an index for one or more
> arrays and then 2) get summary statistics based on the index. I have 2
> issues:
> 

First of all, based on a cursory look of your code, I should note that you may 
opt to use Statistics-Descriptive instead:

http://search.cpan.org/dist/Statistics-Descriptive/

Caveat: I'm its maintainer on CPAN.

> 1. I would like to be able to create the index conditional on the
> values of another array, e.g., conceptually something like:
> 
> my @index = &defindex(\...@a,\...@b,\...@c)  for \...@dv >150 & dv < 800

I don't understand this code. Do you want to use perldoc -f map:

http://perldoc.perl.org/functions/map.html

?

A few notes:

1. Don't do ampersand-subroutine: 
http://www.perlfoundation.org/perl5/index.cgi?subroutines_called_with_the_ampersand

2. You have three arrays passed as a reference. Please consider using named 
arguments, in case you have too many parameters:

<<<<<<<<
print_details(
        {
                first => "John",
                last => "Doe",
                city => "Tel Aviv",
                .
                .
                .
        }
);
>>>>>>>

>
> However, I have no idea how to write the code to do this.   Ideally I
> would be able to have several constraints (e.g., filter by reaction
> time, accuracy, etc).  Any clues?  Is there a specific keyword or
> topic I should search?

I don't understand. You may look at some list operations from:

1. http://www.shlomifish.org/lecture/Perl/Newbies/lecture2/useful_funcs/

2. http://search.cpan.org/perldoc?List::Util

3. http://search.cpan.org/dist/List-MoreUtils/

> 
> 2. This following section is redundant across the subroutines, but I
> cannot figure out how put it into another subroutine and return the
> result in a way that I can use it. I think I'm just not understanding
> how to correctly return/use the hash with multiple values per key. ( I
> want to maintain separate subroutines for each measure)
> 
>       my @ke...@{$_[0]};
>       my @valu...@{$_[1]};
>       my %combos = ();
> 
>       my $i=0;
>       foreach (@keys) {
>               my $key=$keys[$i];
>               my $value=$values[$i];
> 
>               push( @{$combos{$key}}, $value );
>               $i++;
>       }

What you're doing here is looping over the keys, discarding the values and 
just incrementing the key. I would write this as (untested):

<<<<<<<<<<<<<<<<<<
sub get_combos_from_kv
{
        my ($keys, $values) = @_;

        my %combos;

        foreach my $i (0 .. $#$keys)
        {
                my $key = $keys->[$i];
                my $value = $values->[$i];

                push @{$combos{$key}}, $value;
        }

        return \%combos;
}
>>>>>>>>>>>>>>>>>>

(There may be a more lispy/haskelly way using the functions in List-Util and 
List-MoreUtils, but this code is also OK.)

And you call it like this:

<<<<<<<<<<<
my $combos = get_combos_from_kv(\...@keys, \...@values);
>>>>>>>>>>>

> 
> Finally, I have no doubt people can suggest how make the code
> generally more perl like and efficient.
> 
> Many thanks in advance for any help,
> Eric
> 
> 
> #!/usr/bin/perl
> 
> use strict qw(vars subs);

Why don't you have "use strict 'refs'" too? I.e:

<<<
use strict;
>>>

> use warnings;

It's good that you have strict and warnings.

> use List::Util qw(sum);
> 
> #example data
> my @a = qw(Sub1 Sub1 Sub1 Sub1 Sub1 Sub1 Sub2 Sub2 Sub2 Sub2 Sub2);
> my @b = qw(left left left right right left right right left right
> right);
> my @c = qw(down up down down up up up down down up up);
> my @dv= (.87,.2,.655,.7,.5,.3,.1,.45,.70,.900,.3);

I should note that these decimal floating-point fractions will not be exact, 
due to their constraints as base-2 fractions. See:

http://docs.sun.com/source/806-3568/ncg_goldberg.html

(Which I haven't read yet, but am aware of several of its implications.)

> my @acc= qw(c c c i c i c c c i c);
> 
> 
> ###########################################
> my @index = &defindex(\...@a,\...@b,\...@c);

You should never use ampersand-subroutine-call:

http://www.perlfoundation.org/perl5/index.cgi?subroutines_called_with_the_ampersand

> 
> getmean(\...@index,\...@dv);
> getmedian(\...@index,\...@dv);
> getcount(\...@index,\...@dv);
> getmean(\...@index,\...@acc);
> 
> #define the index
> sub defindex {
> 
>       my $i;
>       my $k;
>       my @combined;
>       my @meshed;
> 
>       for ( $i=0; $i<$#_+1; $i++) {

$i < $#_+1 can be written as "$i < @_" which is short for "$i < scalar(@_)". 
This entire loop can be written as:

<<<
for my $i (0 .. $#_)
>>>

Other than that I should note that my personal preference is not to clobber 
the @_ with items and instead to pass them as an array reference.


>               push(@combined,${"array$i"}=$_[$i]);

Why are you using symbolic references and varvarname here:

http://perl.plover.com/varvarname.html

You should use an array.

>       }

> 
>       @meshed = mesh(@combined);
> 
>       $j=0;
>       while (@meshed){
>               my $merged = join('',splice(@meshed,0,$#_+1));

$#_+1 is better written as << scalar(@_) >>

>               $index[$j]=$merged;
>               $i++;
>       }

You should use an array of array refs instead of one big array of concatenated 
fixed-length arrays.

> 
>       return @index;
> 
> } #end defindex
> 

You should return the @index as a reference. It's faster and cleaner. Don't 
clobber the return values.

I'll try to comment on the rest of your code later on.

> [SNIP]

Regards,

        Shlomi Fish

-- 
-----------------------------------------------------------------
Shlomi Fish       http://www.shlomifish.org/
http://www.shlomifish.org/humour/ways_to_do_it.html

Chuck Norris read the entire English Wikipedia in 24 hours. Twice.

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to