Re: Code Interpretation
by muba (Priest) on Jul 28, 2014 at 15:37 UTC
|
You are correct so far.
@allrefs is an array. To get an element out of an array, you use a syntax like $array[ INDEX ]. To get multiple elements out of an array, you'd use @array[ INDEX1, INDEX2, ..., INDEXN ]. That's what's going on here: we sort the values of the %uni_refs hash, and then use those values as the indexes of elements to extract from @allrefs and store them in @refs.
| [reply] [d/l] [select] |
|
| [reply] |
Re: Code Interpretation
by Athanasius (Archbishop) on Jul 28, 2014 at 15:53 UTC
|
Hello Perl_Ally, and welcome to the Monastery!
muba has answered your question; I’ll just add a couple of comments:
The syntax sort { $a <=> $b } does sort numerically, but in ascending order. To get descending order, you reverse $a and $b: sort { $b <=> $a }.
The syntax @array[...] is called an array slice. See perldata#Slices.
Hope that helps,
| [reply] [d/l] [select] |
|
| [reply] |
Re: Code Interpretation
by davido (Cardinal) on Jul 28, 2014 at 16:33 UTC
|
Presumably the %uni_refs hash's values correspond to indices that should exist within @allrefs. So the values are sorted in ascending order forming a list of indices desired. Then they are used to take a slice of @allrefs, in that order.
Seems like a pretty useful way to grab the wanted elements in a desired order, allowing for duplicates and skips as needed.
| [reply] [d/l] [select] |
|
| [reply] |
Re: Code Interpretation
by ikegami (Patriarch) on Jul 28, 2014 at 21:29 UTC
|
Assuming every value of %uni_refs is a unique index of @allrefs (which I judge to be quite likely), the following is a solution that scales better (O(N) instead of O(N log N)).
my %keep = map { $_ => 1 } values %uni_refs;
my @refs = @allrefs[ grep $keep{$_}, 0..$#allrefs ];
| [reply] [d/l] [select] |
|
Edit: Apologies to ikegami for misreading his code. While the benchmark still more or less stands, my assertion that the output would differ was incorrect.
Your code will not produce the same output as the OP's. You indeed removed an O(N log N) loop, but at the cost of the sort. Even then, thanks to the grep and extra hash loop versus slice, the OP's (sorted) performance is 300% better than your unsorted code. Both unsorted, the gap widens to nearly 1000% with N = 1x105.
With N = 1x106, the gap shrinks a bit to 214% and 738%, respectively.
Perhaps I'm missing your point, though? Edit: Yup!
| [reply] [d/l] [select] |
|
Your code will not produce the same output as the OP's.
As long as grep doesn't change the order of 0..$#allrefs, I'd expect the result to be in the same order as by the OP.
About the performance point, this depends on wether %uni_refs has the same size as @allrefs, or not. If %uni_refs is just a small part of @allrefs, ikegami's solution is faster even with the additional sort...
Update: Oops, I should take a course in reading benchmarks ... map+grep is slower, anyway. Yet I'm not completely convinced. There must be an edge case where it is faster :-)
| [reply] [d/l] [select] |
|
Re: Code Interpretation
by blue_cowdawg (Monsignor) on Jul 28, 2014 at 15:43 UTC
|
use strict;
use Data::Dumper;
my @allrefs;
my %uni_refs = (
qw [ a 1 b 2 c 3 ]
);
print Dumper \%uni_refs;
my @refs = @allrefs[ sort {$a <=> $b} values %uni_refs ];
print Dumper \@allrefs;
print Dumper \@refs;
and here is what the output looks like:
$VAR1 = {
'c' => '3',
'a' => '1',
'b' => '2'
};
$VAR1 = [];
$VAR1 = [
undef,
undef,
undef
];
Question is: what was the intended outcome?
Peter L. Berghold -- Unix Professional
Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
| [reply] [d/l] [select] |
|
blue_cowdawg: Thanks for the attention.
I wasn't sure of the intent, which is why I was looking for help interpreting. This is an existing script written by somebody else which I'm hoping to update to be more useful.
The quoted line of code comes at the end of a sub. @allrefs should be an already populated array, which is why your output shows undef.
| [reply] |
|
| [reply] |
Re: Code Interpretation ( ppi_dumper )
by Anonymous Monk on Jul 28, 2014 at 20:56 UTC
|
PPI::Document
PPI::Statement::Variable
PPI::Token::Word 'my'
PPI::Token::Symbol '@refs'
PPI::Token::Operator '='
PPI::Token::Symbol '@allrefs'
PPI::Structure::Subscript [ ... ]
PPI::Statement::Expression
PPI::Token::Word 'sort'
PPI::Structure::Block { ... }
PPI::Statement
PPI::Token::Symbol '$a'
PPI::Token::Operator '<=>'
PPI::Token::Symbol '$b'
PPI::Token::Word 'values'
PPI::Token::Symbol '%uni_refs'
PPI::Token::Structure ';'
perldoc PPI::Structure::Subscript PPI::Structure::Subscript is the class used for square and curly braces that specify one element of an array or hash (or a slice/subset of an array or hash)
So then [perldoc://subscript], [perldoc://subset], [perldoc://slice] subscript, subset, slice -> perldata#Subscripts,
perldata#Slices,
perllol#Slices,
perlintro#Arrays,
perlfunc#delete EXPR,
They are also discussed in the free book (reviewed and recommended by Perl Tutorial Hub) Modern Perl by chromatic a loose description of how experienced and effective Perl 5 programmers work....You can learn this too.
| [reply] [d/l] |
A reply falls below the community's threshold of quality. You may see it by logging in. |