in reply to Fastest way to grep multiple time on some array
If you work your way forwards from the end of the array, you can splice out the elements that match as you go, thus removing them from the array so they are not examined again. I store the results in a HoA keyed by letter.
use strict; use warnings; use Data::Dumper; my @arr; push @arr , ( q{A} .. q{Z}, q{0} .. q{9} )[ int rand 36 ] . sprintf( q{%04d}, int rand 10000 ) for 1 .. 25; print Data::Dumper ->Dumpxs( [ \ @arr ], [ qw{ *arr } ] ); my %letters = (); foreach my $letter ( q{A} .. q{Z} ) { last unless @arr; my $rxLetter = qr{$letter}; foreach my $idx ( reverse 0 .. $#arr ) { next unless $arr[ $idx ] =~ $rxLetter; push @{ $letters{ $letter } }, splice @arr, $idx, 1; } } print Data::Dumper ->new( [ \ %letters, \ @arr ], [ qw{ *letters *arr } ] ) ->Sortkeys( 1 ) ->Dumpxs();
The results.
@arr = ( 'V1348', 'O5896', 'Q3648', '18290', 'J6417', 'G5924', '46458', 'O1853', 'T3800', 'X2826', 'G0512', 'K7895', 'X1951', 'C7754', 'S7722', 'P8593', 'K7636', 'F6980', 'U0711', 'E9196', 'C9297', 'O8023', 'T2141', '67437', 'K8979' ); %letters = ( 'C' => [ 'C9297', 'C7754' ], 'E' => [ 'E9196' ], 'F' => [ 'F6980' ], 'G' => [ 'G0512', 'G5924' ], 'J' => [ 'J6417' ], 'K' => [ 'K8979', 'K7636', 'K7895' ], 'O' => [ 'O8023', 'O1853', 'O5896' ], 'P' => [ 'P8593' ], 'Q' => [ 'Q3648' ], 'S' => [ 'S7722' ], 'T' => [ 'T2141', 'T3800' ], 'U' => [ 'U0711' ], 'V' => [ 'V1348' ], 'X' => [ 'X1951', 'X2826' ] ); @arr = ( '18290', '46458', '67437' );
I hope this is of interest. I'm not sure what the performance will be like, I gather that splice can involve a lot of work behind the scenes.
Cheers,
JohnGG
|
|---|