I wrote a generic function to call a stored procedure. I tried to use a multidimensional array to pass the parameters. Now it is possible, that the procedure only takes one parameter, so my multidimensional array has also only one parameter. But the lenght of such an array is 2!
$MyParameters = ("param1_name", "param1_value")
$MyParameters.Length returns 2!! Strange, why? It should return 1
$MyParameters returns correctly:
param1_name
param1_value
If I write:
$MyParameters = ("param1_name", "param1_value"), ("param2_name", "param2_value")
$MyParameters.Length returns also 2 which is correct. $MyParameters returns correctly all four elements:
param1_name
param1_value
param2_name
param2_value
Any reasons for that? Am I missing something?
What you are trying to do is creating an array of multi value object.
Here is an example to solve that issue:
$x = ,("param1","param2","param3")
x.Lenght
Will return 1 which is correct for your issue.
$x = ,("param1","param2","param3"),("param1","param2","param3")
x.Lenght
Will return 2
$x = ,("param1","param2","param3"),("param1","param2","param3")
x[0].Lenght
will return 1, thats because $x[0] is array with one element.
In addition, If you would like to create an Array of Arrays this is the way to do it:
$x = #("param1","param2","param3"),#("param1","param2","param3")
$x.Lenght
#2
$x[0].Lenght
#3
Related
I've been stuck with this for a while and I couldn't find something similar asked previously (or I have failed in doing so)
My situation is fairly simple: I have a cell array of objects. They are all the same object and I have a get function for this kind of object which is: get (obj, attr), where obj is the object in question and attr is a integer from 1-6. Depending on the number the get function returns the corresponding attribute.
I would like to obtain all of my "position" attributes from all my objects which are in the corresponding cell array (this would be attr = 2). I know that cellfun performs a function on all cells, but the question is, how do I use my get function here for all my objects, taking into account that the function is get (obj, attr) ?
Thanks in advance
Firstly, by using get as a custom function you are shadowing the built-in get function - this is bad practise!
With this in mind, and to avoid confusion with the built-in get function which has similar syntax, I'm going to use getattr as a stand-in for your custom function which accpets an object and an integer 1 to 6.
pos = cellfun( #(obj) getattr( obj, 2 ), myCellOfObjects, 'uni', 0 );
By specifying 'uni', 0, the output doesn't have to be scalar and will be put into a cell array. This is useful when, for example, you have a multi-element array for your position.
This is equivalent to the following loop:
pos = cell( numel(myCellOfObjects), 1 );
for ii = 1:numel(pos)
pos{ii} = getattr( myCellOfObjects{ii}, 2 );
end
If ever in doubt about cellfun or arrayfun, just write a loop first - they are essentially the same but more concise.
There is a trick to this some are unaware of: you can pass multiple arguments to cellfun like this:
cellfun(#(obj,attr) get(obj,attr), {obj1,obj2},{attr1,attr2},'uni',0)
if you want to get one attribute of the cellarray (instead of providing an attribute for every object in the cellarray), then you can simply use this
cellfun(#(x) getattr(x,attr),obj,'uni',0)
put into anonymous function for convenience:
get_attr = #(obj,attr) cellfun(#(x) getattr(x,attr),obj,'uni',0)
%use:
get_attr(obj_in_cellarray,'myattribute')
%returns cell array of object attributes
I haven't run any of these functions since you didn't provide any example data / code. Please test and feedback.
I am trying to create an array where each element is an empty array.
I have tried this:
var result = Array.fill[Array[Int]](Array.empty[Int])
After looking here How to create and use a multi-dimensional array in Scala?, I also tried this:
var result = Array.ofDim[Array[Int]](Array.empty[Int])
However, none of these work.
How can I create an array of empty arrays?
You are misunderstanding Array.ofDim here. It creates a multidimensional array given the dimensions and the type of value to hold.
To create an array of 100 arrays, each of which is empty (0 elements) and would hold Ints, you need only to specify those dimensions as parameters to the ofDim function.
val result = Array.ofDim[Int](100, 0)
Array.fill takes two params: The first is the length, the second the value to fill the array with, more precisely the second parameter is an element computation that will be invoked multiple times to obtain the array elements (Thanks to #alexey-romanov for pointing this out). However, in your case it results always in the same value, the empty array.
Array.fill[Array[Int]](length)(Array.empty)
Consider also Array.tabulate as follows,
val result = Array.tabulate(100)(_ => Array[Int]())
where the lambda function is applied 100 times and for each it delivers an empty array.
I want to replace the value of the fields in a structure array. For example, I want to replace all 1's with 3's in the following construction.
a(1).b = 1;
a(2).b = 2;
a(3).b = 1;
a([a.b] == 1).b = 3; % This doesn't work and spits out:
% "Insufficient outputs from right hand side to satisfy comma separated
% list expansion on left hand side. Missing [] are the most likely cause."
Is there an easy syntax for this? I want to avoid ugly for loops for such simple operation.
Credits go to #Slayton, but you actually can do the same thing for assigning values too, using deal:
[a([a.b]==1).b]=deal(3)
So breakdown:
[a.b]
retrieves all b fields of the array a and puts this comma-separated-list in an array.
a([a.b]==1)
uses logical indexing to index only the elements of a that satisfy the constraint. Subsequently the full command above assigns the value 3 to all elements of the resulting comma-separated-list according to this.
You can retrieve that the value of a field for each struct in an array using cell notation.
bVals = {a.b};
bVals = cell2mat( bVals );
AFAIK, you can't do the same thing for inserting values into an array of structs. You'll have to use a loop.
I have an object I defined with a method, childNodes(), which returns an array. When I do something like:
my #arr = obj->childNodes() I can clearly see that it can properly return an array.
My problem is that when I try to use this method to set the attribute of another class object, Perl decides I just want the length of childNodes() rather than the full array. This is not at all what I want and ruins everything. The code I'm using for this is:
$self->{'_arr'} = obj->childNodes()
How can I make this set $self->{'_arr'} to an array instead of just a scalar number?
Thanks in advance!
When you evaluate an array in scalar context, it returns the length of the array.
You want a reference to the array:
$self->{'_arr'} = [ obj->childNodes() ];
See perldoc perlref.
I'm running the following code and I'm attempting to print the first element in the #rainbow array through the fifth-from-last element in the #rainbow array. This code works for any positive indices within the bounds of the array, but not for negative ones:
#rainbow = ("a".."z");
#slice = #rainbow[1..-5];
print "#slice\n";
You want
my #slice = #rainbow[0 .. $#rainbow - 5];
Be careful, 1 is the second element, not the first.
The .. operator forms a range from the left to right value - if the right is greater than or equal to the left. Also, in Perl, array indexing starts at zero.
How about this?
#slice = #rainbow[0..$#rainbow-5];
$#arraygives you the index of the last element in the array.
From the first two sentences for the range operator, documented in perlop:
Binary ".." is the range operator, which is really two different operators depending on the context. In list context, it returns a list of values counting (up by ones) from the left value to the right value. If the left value is greater than the right value then it returns the empty list.
When the code doesn't work, decompose it to see what's happening. For instance, you would try the range operator to see what it produced:
my #indices = 1 .. -5;
print "Indices are [#indices]\n";
When you got an empty list and realized that there is something going on that you don't understand, check the documentation for whatever you are trying to do to check it's doing what you think it should be doing. :)