1

I would like is possible in perl to get an array ref from a hash or to convert a ref hash into ref array !?

For example :

%trad = ('January','Jan','February','Feb');
$ref = \%trad;      # made a reference on hash
$ref2 = [%{$ref}];  # convert ref hash to ref array

in other way we can write :

$ref2 = [%{\%trad}];

But this code is an illusion of ref array on hash because contruction $ref = [...] creates a reference to an anonymous array created by copying elements from hash by Perl.

You can see that by trying to fill array pointed by $ref2 which has no effect on hash !

Is there a way to operate directly on hash directly in memory zone by using a real ref array like casting method in C !?

6
  • 1
    This smells a lot like an XY problem. What are you trying to accomplish here? Commented May 9, 2018 at 10:14
  • Notrhing in particular :-) We can read in lot of places that hash and array are almost similar :-) Hash is a special Array with specific methods to manipulate data in it. References give an opportunity to manipulate these objects in elegant manner by saving memory for me. What do you mean by XY problem ? :-) Commented May 9, 2018 at 10:51
  • OK for XY problem : en.wikipedia.org/wiki/XY_problem. My goal is really to known if we can get a real ref array on a hash... Commented May 9, 2018 at 11:13
  • No, they aren't similar in that sense - they're both data structures, but they work in different ways. The fact that you're talking about a 'real ref array' means I think you're latching on to how you would do something in C - and perl doesn't work that way. Hence why I'm asking what you're actually trying to accomplish. How hashes really work Commented May 9, 2018 at 11:24
  • Hashes and arrays are completely different data structures. A C-style cast would be completely useless. In Perl or in C. Commented May 10, 2018 at 1:47

2 Answers 2

5

You cannot operate on a hash directly, because perl doesn't work that way. References are not pointers in the C sense. You cannot directly access memory.

Hashes and arrays might look similar on the surface - because you can cast between them with:

my @array = %hash; 
   %hash = @array; 

And it 'works'. But this disguises that behind the scenes, they are different beasts. @array is still an ordered list of elements. %hash is still a non-deterministic ordered dictionary. The reason this work at all, is because enumerating a %hash in a list context, returns paired values. And you can populate a hash with a list of paired values.

Indeed, that's pretty much what;

my %hash = ( 'January' => 'Jan',
             'February' => 'Feb');

Is actually doing. You're supplying a list to the hash, and it's doing the right thing with it - associating the 'key' with the 'value' as paired values. ( => is basically the same as a comma, but it's often used like this because it's clearer to show the key-value associations).

Here's an older article on how hashes work - it's changed somewhat in the intervening time, but the principle is similar - there are buckets, and hashes keys map into the buckets based on an internal algorithm.

When you enumerate the whole hash in a list context - it returns the key-value pairs in an effectively random order each time, because that's how it's 'working' behind the scenes with the hash-lookup mechanism.

But this means looking for a "real array ref" and "operating on a hash directly" isn't really meaningful - perl doesn't support doing that like you could in C, because that's not how the language works.

If you really want to know what's happening behind the scenes - perlguts will give you a lot of detail. But it's mostly irrelevant to the process of coding in perl.

Sign up to request clarification or add additional context in comments.

Comments

0

OK, it's more clear for me now. Thanks to took time to answer my question.

Effectively my confusing was to believe that Perl references work like references in C.

I found this article http://www.perlmonks.org/?node_id=504196 which explains this trick but it don't precise this new reference created binds to anonymous array or hash :-(

It's pity that we can't do that, in some case it could be useful maybe.

For example to get the size of a hash ( number of key/value ) we can write :

$size_hash = ( $#{ [ %{\%hash} ] } +1 ) / 2;

I use a reference from a Hash which is converted to Array reference and after we can get easily size of this array and divide by 2 to get result.

I know, there are lot of methods to reach same goal but I found this method more "elegant" and I believed less consummative in memory :-( Not in reality because it creates an anonymous array with hash data :-(

5 Comments

Premature optimisations are the root of all evil. Also: why do you need to get the size of your hash? scalar keys %hash should do the trick nicely.
Re "Effectively my confusing was to believe that Perl references work like references in C.", A reference is a pointer with which you can't do pointer arithmetic. They are otherwise identical.
Re "to get the size of a hash ( number of key/value ) we can write", my $size = keys(%hash); is preferred (O(1) time and space instead of O(N) time and space).
Re "It's pity that we can't do that, in some case it could be useful maybe.", Never useful. The data structures are completely different, so a cast would never work.
You could make it so the values of an array and a hash are shared such that if you change one, the other is changed too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.