The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Iterator::Array::Jagged - Quickly permute and iterate through multiple jagged arrays.

SYNOPSIS

        use Iterator::Array::Jagged;
        
        # Build up a set of data:
        my @data = (
                [qw/ a b /],
                [qw/ c d /],
                [qw/ e f g /]
        );
        
        # Iterator in object-oriented mode:
        my $iterator = Iterator::Array::Jagged->new( data => \@data );
        while( my @set = $iterator->next )
        {
                print "Next set: '" . join("&", @set) . "'\n";
        }# end while()
        
        # Iterator is a subref:
        my $itersub = Iterator::Array::Jagged->get_iterator( @data );
        while( my @set = $itersub->() )
        {
                print "Next set: '" . join("&", @set) . "'\n";
        }# end while()
        
        # Functional callback style:
        Iterator::Array::Jagged->permute(sub {
                my (@set) = @_;
                print "Next set: '" . join("&", @set) . "'\n";
        }, @data );

Each example in the code above code prints the following:

        Next set: b&c&e'
        Next set: a&d&e'
        Next set: b&d&e'
        Next set: a&c&f'
        Next set: b&c&f'
        Next set: a&d&f'
        Next set: b&d&f'
        Next set: a&c&g'
        Next set: b&c&g'
        Next set: a&d&g'
        Next set: b&d&g'

DESCRIPTION

Iterator::Array::Jagged can permute through sets of "jagged" arrays - arrays of varying lengths.

Iterator::Array::Jagged works much like the odometer in an automobile. Except that each set of "numbers" can have any kind of data you want, and each set can contain 1 or more elements.

Iterator::Array::Jagged is stable and ready for production use as of version 0.05.

METHODS

new( %args )

Constructor. %args should included the element data which contains the arrayref of arrayrefs that you wish to iterate through.

next( )

Returns an array representing the next iteration of the permutation of your data set. See the synopsis for an example.

get_iterator( @data )

Returns a coderef that, when called, returns the next set of data until there are no more permutations. See the synopsis for an example.

permute( $subref, @data )

Calls $subref for each permutation in @data. This is currently BY FAR THE FASTEST METHOD AVAILABLE.

BENCHMARKS

After the initial release of Iterator::Array::Jagged, some people were wondering if there was any benefit to using I::A::J over another older module Algorithm::Loops and its NestedLoops method. So I did some benchmarking and found some mixed results.

                    Rate I::A::J OO A::L::NL func I::A::J iterator A::L::NL iterator I::A::J permute
  I::A::J OO        4.19/s         --           -3%             -19%              -29%            -45%
  A::L::NL func     4.32/s         3%            --             -16%              -27%            -43%
  I::A::J iterator  5.15/s        23%           19%               --              -12%            -32%
  A::L::NL iterator 5.88/s        40%           36%              14%                --            -22%
  I::A::J permute   7.58/s        81%           75%              47%               29%              --

Depending on the size and depth of the jagged array data passed in, the results vary slightly. However, the order in which each method finishes is the same. Iterator::Array::Jagged->permute is fastest by a signifigant margin over Algorithm::Loops::NestedLoops. On the opposite end of the spectrum we have the OO method of Iterator::Array::Jagged which comes in at nearly half the speed of the permute option.

The benchmark script that was used is shown in the next section.

Benchmarks were done on a server with the following specs:

CPU:

Intel(R) Core(TM)2 CPU 6400 @ 2.13GHz stepping 02

RAM:

2Gb

The Benchmark Script

  #!/usr/bin/perl -w
  
  use strict;
  use Time::HiRes qw(gettimeofday);
  use Benchmark qw' :all ';
  
  use Algorithm::Loops 'NestedLoops';
  use Iterator::Array::Jagged;
  
  
  my @data = ();
  for my $var ( 1...4 )
  {
    my @set = ();
    my $max = $var % 2 ? 10 : 11;
    for my $val ( 1...$max )
    {
      push @set, "var$var=val$val";
    }# end for()
    push @data, \@set;
  }# end for()
  
  cmpthese( 20, {
    'I::A::J OO'        => sub { do_iterator_array_jagged( @data ) },
    'A::L::NL iterator' => sub { do_nestedloops_iterator( @data ) },
    'A::L::NL func'     => sub { do_nestedloops_func( @data ) },
    'I::A::J permute'   => sub { do_iaj_permute( @data ) },
    'I::A::J iterator'  => sub { do_iaj_iterator( @data ) },
  });
  
  
  sub do_iaj_iterator
  {
    my $iter = Iterator::Array::Jagged->get_iterator( @_ );
    while( my @set = $iter->() )
    {
    }# end while()
  }# end do_iaj_iterator()
  
  
  sub do_iaj_permute
  {
    Iterator::Array::Jagged->permute( sub { }, @_ );
  }# end do_iaj_permute()
  
  
  sub do_iterator_array_jagged
  {
    my @data = @_;
    my $iter = Iterator::Array::Jagged->new( data => \@data );
    while( my $set = $iter->next )
    {
    }# end while()
  }# end do_iterator_array_jagged()
  
  
  sub do_nestedloops_func
  {
    NestedLoops( \@_, sub { } );
  }# end do_nestedloops_func()
  
  
  sub do_nestedloops_iterator
  {
    my @data = @_;
    my $iter = NestedLoops( \@data );
    while( my @set = $iter->() )
    {
    }# end while()
  }# end do_nestedloops()

BUGS

It's possible that some bugs have found their way into this release.

Use RT http://rt.cpan.org/NoAuth/Bugs.html?Dist=Iterator-Array-Jagged to submit bug reports.

AUTHOR

John Drago mailto:jdrago_999@yahoo.com

COPYRIGHT AND LICENSE

Copyright 2007 John Drago, All rights reserved.

This software is free software. It may be used and distributed under the same terms as Perl itself.