I'm a beginner (a wet lab biologist, who has to fiddle a bit with bioinformatics for the first time in my life) and today I've got stuck on one problem: how to parse an array to a hash of arrays in perl?
This doesn't work:
#myhash{$key} = #mytable;
I've finally circumvented my problem with a for loop:
for(my $i=0;$i<=$#mytable;$i++){$myhash{$key}[$i]=$mytable[$i]};
Of course it works and it does what I need to be done, but it seems to me not a solution to my problem, but just a way to circumvent it... When something doesn't work I like to understand why...
Thank you very much for your advice!
If you are asking how to put an array as one value of a hash, you do this by taking a reference to the array, since references are scalars and the values of hashes must be scalars. This is done with the backslash operator.
$myhash{$key} = \#mytable;
The for loop you describe creates such a reference through autovivification, as $myhash{$key}[0] creates an array reference at $myhash{$key} in order to assign to its index. Also note that the difference between taking a reference and copying each value is that in the former case, changes to the array after the fact will also affect the values referenced via the hash value, and vice versa.
$mytable[5] = 42; # $myhash{$key}[5] is also changed
As Grinnz mentioned you can save a reference to an array, but any change on the array latter will be reflected in hash (it is same data).
For example if you reuse same array in the loop then data in hash will reflect last iteration of the loop.
In such case you will want a copy of array stored in the hash.
#{$hash{$key}} = #array;
Programming Perl: Data strutures
Related
I've started working on a program which is in Perl and has to be transformed into C.
There are a lot of subroutines which have structure member accessing which is unfamiliar to me, because I have little to no knowledge about Perl syntax and structure flow.
Example:
$ref->{$struct2[$value]->{field1}}->{struct_insideStruct2}->{$ref2->{field}}
$ref is a third structure
$ref2 is a local copy of a parameter which is of type struct1
My question is: How do you create a line like this in C?
Do I need to create nested multiple structures?
I need to understand how multiple access operators in Perl works and if I can create something similiar in C, thanks in advance.
I recommend to not try to directly translate between languages, as this likely results in a clumsy and unnatural code. That would certainly be the case here, as commented further down. The best I can do for this quest is to explain what the expression does
$ref -> { $struct2[$value]->{field1} }
-> { struct_insideStruct2 }
-> { $ref2->{field} }
The $ref is a reference to a hash (associative array); it's OK to think of it as a pointer to a hash. One can tell because the -> ("arrow") operator dereferences, and the {...} on its right means that on its left there must be a hash reference; this returns a value that it points to.
In this case, the key with which it is dereferenced (the index into the associative array) involves an element of the array #struct2 at index $value; that element is another hash reference, being dereferenced (indexed into) with a key field1 (string literal†).
What this returns is another hash reference, which is then indexed into (dereferenced) with the key struct_insideStruct2 (string), and this again returns a hash reference.
That last one is indexed with a key which itself is produced by dereferencing another hash reference, $ref2, with a key field (string).
This is an example of a Perl complex data structure. How do you like it? I don't, not very much. Even in Perl, ideally I'd like to see this rewritten as a class, as it goes too deep and wide and so it packs too much complexity without any supporting structure which a class can provide.
If you still wish to indeed and really do that kinda thing in C, you can. May want to find a good hash implementation (or use structs and nest them carefully), and probably to dust off your function pointer syntax and such. But I would recommend to not get into all that.
Instead, once you understand the deep-nested data structure explained above, and the data it represents, find a way to implement what it means and does in your code in a native C way. We always want to use logic, techniques, and idioms native to the language at hand.
Along with linked documentation also see the short and sweet perlintro. The full reference for Perl's references is perlref.
†Normally such "barewords" need be under quotes, 'string' (or using "", or q() or qq() operators ...). But if that is a sole thing between {} then the quoting may be omitted.
i knew its a weird Idea to think about, i want to know if it is possible to reverse the mechanism of sorting, (i dont want to reverse the order).
for example lets say i have a random array of integers, then i sorted the array with quicksort method, now i want to go back and un-sort the array and get it back to the it was.
you may suggest i save a copy of the array, thats not what i want, think of it as a time line and have the ability to go backward or forward of sorting method.
and if it is possible please consider showing me the best way to do it with Delphi XE.
Thanks in advance.
It is not possible to unsort. You have to either:
create a separate array that holds a copy of the values and then sort that array so that you can preserve the original array.
create a separate array that holds pointers/indexes to the values in the original array, and then sort the second array using the values it refers to.
I usually use a function that given an array returns an array of the sorted indexes.
This way you will always have the original data and you will be able to access the data in a sorted way using something like:
for jIndex in ASortedIndexesArray do
ShowMessage(AOriginalArray[jIndex]);
Hope this helps.
Mirko
If you want to think of it as a time line and have the ability to go backward or forward of sorting method then organize it like a timeline - with records in a file. Save each step and you will be able to reproduce it.
If the array is of integers the indices will not help you as one index (a pointer) takes the same memory as one array element. If you lack RAM use a file to store and retrieve the array. If you use larger data structures you can create, store and retrieve indices as David suggested.
You could log the swapping actions that quicksort (or whatever sorting algorithm you use) does to a list and then go forward and backward in that list to undo/redo these actions. Not simple to implement, but doable.
If i write in Lua
local var = {1,2,3,4,5,6}
Variable var is array.
If i want to keep it as array (not hash), i must use table.insert, table.remove etc.
This code will turn it into hash:
var["key"] = 4
QUESTION:
Does this code turn array variable into hash?
local var = {1,2,3,4,5}
var[4] = "string"
var[6] = "string"
var[1] = "string"
As others already pointed, Lua only has tables. Internally, the values you put in the table, may be stored in its array or hash part, but it's an implementation detail that users don't need to worry about.
In your particular case, the keys will be stored in the array part only (even after assignment), as you are not creating any new keys. According to a detailed description in Lua Performance Tips ("About tables" section), the initial assignment will allocate 6 slots in the array part and then you just re-assign those. If you add var[7] = "string", then this value goes into the hash part and this will trigger a re-hash as the hash part has size 0 at this point. Lua will calculate how many slots are needed to accommodate all values in the array part (7 now) and "chooses as the size of the array part the largest power of 2 such that more than half the elements of the array part are filled".The array part will now have 8 slots and the hash part will still have size 0 as there are no elements to go there.
QUESTION: Does this code turn array variable into hash?
So the answer to this question is "no" (if by "turn into hash" you mean that the table gets a non-zero hash part). If you do var[8] = "string" (without assigning var[7]), the hash part will get non-zero size, but if you later do var[7] = "string", this will trigger another re-hash as this element won't fit in the hash part and all these elements will be assigned to the array part again.
Lua is trying hard to keep the most appropriate structure for the elements you have in the table, but the changes to the structure itself are only done during re-hashing.
You are trying to draw a distinction between "arrays" and "hashes" which does not exist in Lua. They're all tables. Some of them just have keys which aren't all positive integers.
I have a vector array that contains Time values in an asceding order. With relational expressions I can obtain subset values from that array, after that I need the first value of that subset without creating new variables.
For example.
Time is an column vector, then I can use Time(something==X) to get a subset values of Time, but then I need the first value of Time(something==X), I can't use Time(something==X)(1) like some programming languages u.u
Unfortunately with MATLAB you need to use temporary variables. It doesn't support this kind of indexing, though it is quite natural and I would love if they supported it.
You would have to do this:
x = Time(something==X);
y = x(1);
Octave does have the ability of doing this kind of indexing though. The only way I can think of you escaping this is if you use cell arrays. However, if you want to use a normal vector, then you're SOL.
EDIT: May 13th, 2014 - Referencing David's comment, it is possible to do this without a temporary variable, but readability is very poor. In the end, a temporary variable is still the better way for readability and reproducibility. Check the following SO post that he has referenced:
How can I index a MATLAB array returned by a function without first assigning it to a local variable?
Here is a code snippet, that shows what I want and the error, that follows:
a = [1, 2];
m = containers.Map('KeyType','char', 'ValueType','any');
m('stackoverflow.com') = a;
pull_the_first_element_of_the_stored_array = m('stackoverflow.com')(1);
??? Error: ()-indexing must appear last in an index expression.
How do I access an element of the array, which is in turn a value of a map object?
I could have done this:
temp = m('stackoverflow.com');
pull_the_first_element_of_the_stored_array = temp(1);
But I do not want to create an intermediate array only to pull a single value out of it.
EDIT : This is a duplicate of How can I index a MATLAB array returned by a function without first assigning it to a local variable? The answer is there.
This is another case where you can get around syntax limitations with small helper functions. EG:
getFirst = #(x)x(1);
pull_the_first_element_of_the_stored_array = getFirst(m('stackoverflow.com'));
This still needs two lines, but you can often reuse the function definition. More generally, you could write:
getNth = #(x, n) x(n);
And then use:
getNth (m('stackoverflow.com'),1);
Although this question is a duplicate of this previous question, I feel compelled to point out one small difference between the problems they are addressing, and how my previous answer could be adapted slightly...
The previous question dealt with how to get around the syntax issue involved in having a function call immediately followed by an indexing operation on the same line. This question instead deals with two indexing operations immediately following one another on the same line. The two solutions from my other answer (using SUBSREF or a helper function) also apply, but there is actually an alternative way to use SUBSREF that combines the two indexing operations, like so:
value = subsref(m,struct('type','()','subs',{'stackoverflow.com',{1}}));
Note how the sequential index subscripts 'stackoverflow.com' and 1 are combined into a cell array to create a 1-by-2 structure array to pass to SUBSREF. It's still an ugly one-liner, and I would still advocate using the temporary variable solution for the sake of readability.