There are a variety of ways of looking at this problem, however, in playing with it, I stumbled because I wouldn't figure out your intent. Looking at your code snippets, I see that each of them is four nested loops! This absolutely won't scale. You state that you believe your way is slow, but I would suggest that you prove your way is slow before continuing. If you have a small data set, it might still be okay.
Further, I still don't know exactly what you're trying to accomplish. I wrote the following test program which, from what I can tell, mimics what you're trying to do, but it still doesn't tell me why you're trying to do it:
use strict; use Data::Dumper; my @found = map { {ID=>$_} } qw( abC e8q xxx 11m ); my $matched = 0; my %manager = ( 1 => { bob => { members => [qw{ abc def gdF }] } }, 7 => { alice => { members => [qw{ 5hg 8DF 9iw }] }, charlie => { members => [qw{ 2je e8q 11M }] } } ); foreach my $id (keys %manager){ foreach my $manager (keys %{$manager{$id}}){ for my $i (0..$#{$manager{$id}{$manager}{'members'}}){ my $index=0; foreach my $emp (@found){ if ($emp->{'ID'}=~/$manager{$id}{$manager}{'members'}[$ +i]/i){ splice(@found, $index, 1); print $emp->{'Name'} . "\n"; $matched++;} $index++;}}}} print "Matched: ($matched) ", Dumper \@found;
Give that the first data structure is so complex, I would suggest that your task it to rethink the construction of said structure or to construct another structure that accomplishes the needed task. For example, we see that each manager (Bob, Alice, and Charlie) has an array of members. In you regular expression, you attempt to match this in a case-insensitive manner, but your match will match if an ID is a substring of a member. If you want to make an exact, but case insentive match, perhaps while constructing the complex data structure, you can make those "members" the keys in a hash (while lower-casing them). This allows the following:
@found = grep { ! exists %members{ lc $_->{ID} } } @found;
(This appears to match your logic where the items in the @found array are those items that were not found in the data structure!)
Thus, instead of having four nested loops, we have one pass through a data structure.
Additionally, you could try putting this data in a database and taking advantage of the capabilities inherent their.
In short, there are a variety of ways to deal with your problem, but if you give us a higher level description of what you need to accomplish, we may be better able to help you.
Side note, instead of using splice to get rid of found elements, have you thought about using push to add the "not found" elements onto a different array? The logic would be easier to follow.
if ( $emp->{ID} =~ /$some_regex/i ) { push @emp_found => $emp; print $emp->{'Name'} . "\n"; } else { push @emp_ot_found => $emp; }
Cheers,
Ovid
New address of my CGI Course.
Silence is Evil (feel free to copy and distribute widely - note copyright text)
In reply to Re: splice question (change your data structure)
by Ovid
in thread splice question
by tbone
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |