On Dec 4, 2009, at 8:32 AM, Shlomi Fish wrote:

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.

Thank you. I'll keep this mind, but I'm writing this, in part, to get a deeper understanding of some concepts.

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

?

If so, it's not obvious to me.

To clarify, I want to be able to run the following:

my $index = defindex(\...@a,\...@b);
my @index = @$index;

However, I want to be able to qualify which elements of the passed arrays should be included in the index. So, rows of data might look like this:

@a              @b      @c              @dv     @accuracy
Sub1    left    down    .87     1
Sub1    left    up      .2      1
Sub1    left    down    .655    1
Sub1    right   down    .7      0
Sub1    right   up      .5      0
Sub1    left    up      .3      1
etc.

I want to create an index for say, @a and @b, but conditional that only lines for which the value of @acc that are "1" are included. That is, the index subroutine should skip lines 4 and 5 in the above data. Even more importantly, I want users to be able to apply such arbitrary constraints at the subtoutine call rather than to write code for just this specific example. I'm very interested in learning how to do this sort of thing in general.


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",
                .
                .
                .
        }
);

I will look into this, but I must admit that I thought named arguments are useful because you don't have to remember the order that argument should be passed. In this indexing function, the user should be able to order the arguments in any order they want. Is it still preferable to use named arguments?



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;
}

Thanks! I implemented this code. I was simply not dereferencing the returned hash correctly.



(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;

Honestly, it was simply because it was complaining about my use of refs. I fixed the problem per your suggestion about avoiding symbolic refs and varvarname.



        @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.

I don't understand how to change this. I'm reading up on arrays of arrays, but my $merged variable is string. Can you say more?


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

[SNIP]

Regards,

        Shlomi Fish

Many thanks for all the useful suggestions and notes.

--
-----------------------------------------------------------------
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.

Reply via email to