Sheol has asked for the wisdom of the Perl Monks concerning the following question:

Well, I've got a few objects in perl, that have keys => [] and value => [], or similar attributes in them. I am finding that I am constantly have to search through them the exact same way each time.

That code would be:

for(my $i = 0; $i < count(@{$self->{keys}}); $i++) { my $id = $self->{keys}->[$i]; if($key =~ m!^$id$!) { # do something with the knowledge that we got the correct key # then exit out of function using this loop } } # do something with the knowledge there is no key with that name

Now, 1) There is generally going to a lot of places this will appear, and it is ending up being used more often than some of my functions||methods... that normally shows something bad with coding. 2) There is a chance I may want to change what is done at those sections of code. Mostly because I am pretty damn sure that is not efficent, and I'll probably tweak it later.

So, I am thinking about putting that piece of code somewhere else, and doing something similar to an inline function or macro.

1) Should I have a module that contains a set of functions that should appear in all modules (possibly using @ISA)

2) Should I have an anonymous routine that is loaded as a reference in the modules. Or rather defining the "search" function elsewhere, and loading it as part of the object's propperties

3) Having the functions that make use of it require to have a function for doing the search loaded with @_.

I also plan to have a section of code in this project, that acts as a tied array, but I have yet to decide on that.

Thank you for your help.

Replies are listed 'Best First'.
Re: "array" search
by Aristotle (Chancellor) on Jan 13, 2006 at 06:45 UTC

    Well, that’s a very clumsy data structure you have there. And the code is clumsier than it needs to be, on top of that. What’s that count doing? Looks like a no-op to me. And don’t use for(;;), use for(@LIST):

    for my $i ( 0 .. $#{ $self->{ keys } } ) { my $id = $self->{ keys }->[ $i ]; # ... }

    You could write accessor methods for that part of the data structure so you could say something like:

    for my $i ( 0 .. $self->max_index() ) { my ( $key, $value ) = $self->at( $i ); # ... }

    Or maybe an iterator would be better?

    my $iter = $self->iterator(); while( my ( $key, $value ) = $iter->() ) { # ... }

    Or you could use one of the modules that implement ordered hashes, such as Tie::IxHash, which will let you write this directly using keys and friends.

    Lots of options that depend on what you want to do; for laziness, the tied hash is hard to beat.

    Makeshifts last the longest.

      Hmmm... just checked count in perldoc... what I was trying to do was to compare the $i with length of the array... I could have sworn count() was the function.

      I would write acessors, but I am too lazy (and this search function appears in many objects.. not only one... thats part of the reason I figured an... inline... function (or macro) would work)

      The iterator would appear to be something I wanted to ask about in a future post. What would I have to extend (via @ISA) to make use of it?

      Though like I said, I was already considering using a Tied hash... thanks for pointing me to the first step.

Re: "array" search
by ikegami (Patriarch) on Jan 13, 2006 at 07:11 UTC

    I agree with Aristotle. You should probably use one of the existing Tie:: modules if what you're after is an ordered hash. If you decide not to do this, than the first solution he posted is much easier to read than what you had. He only forgot to replace
    if ($key =~ m!^$id$!) {
    with the much more efficient
    if ($key eq $id) {

      Well, some of the code, yes, I was thinking of making a Tie::Hash. (I think that is the module, it should be easy to figure out)

      Infact the idea of @{$self->{keys}} and @{$self->{values}} was taken from from code in articles on using Tie... right now I was mostly just getting it working first. (Well other than trying to cut down on me writting code over and over again)

      As per $key eq $id... I've read through a few documents and it is very confusing about how that operator works. Or maybe I am reading too deep into what eq does and how it opperates.

        eq is just like ==, except eq compares strings, and == compares numbers.
Re: "array" search
by lidden (Curate) on Jan 13, 2006 at 06:47 UTC
    I think you are trying to to this:
    if($self->{keys}->[$key]){ # do something with the knowledge that we got the correct key # then exit out of function using this loop } # do something with the knowledge there is no key with that name

      Not quite... $key contains a name, not an index. doing $self->{keys}->[ $key ] won't work.

      I could do $self->{keys}->{$key} but I don't think that would work in the case where I might serialise the object.