Is there a way I can create an array inside a dictionary this way (without creating a variable first):
Local $myDictionary = ObjCreate("Scripting.Dictionary")
$myDictionary.Add("firstDictionary", ObjCreate("Scripting.Dictionary")) ;this is ok
$myDictionary.Add("firstarray", []) ;this is wrong
_ArrayAdd($myDictionary.Item("firstArray"), "first element in firstArray")
_ArrayAdd($myDictionary.Item("firstArray"), "second element in firstArray")
This caused a popup with "Error in expression"
Shouldn't this [] return an empty sized array?
And for some reason I cannot add elements when an array is inside a dictionary:
Local $newArray[1]
Local $myDictionary = ObjCreate("Scripting.Dictionary")
_ArrayAdd($newArray,101) ;this is ok
$myDictionary.Add("firstArray", $newArray)
;_ArrayAdd($myDictionary.Item("firstArray"), 102) ; this is wrong
_ArrayAdd(($myDictionary.Item("firstArray")), 102) ; this does not change the dictionary array
_ArrayDisplay(($myDictionary.Item("firstArray"))) ; this still shows 101
There is no way to create an array within a dictionary object, except by using a function that returns an array (StringSplit is a common choice).
Passing a dictionary item ByRef like that is interesting.
Because you have to enclose it in parenthesis (like ($dict.Item("foo"))) it evaluates the expression, so what you are passing is not actually a reference at all. There's no reason why you can't pass it without those parenthesis in theory, but AutoIt doesn't have that functionality yet (and from what Jon has said in the past, updating the COM interface code is a nightmare).
Solutions are to upgrade to the latest beta and use maps, which are a dictionary like collection built into AutoIt.
Alternatively, you have to use 3 lines, create a temporary array and then reassign it after adding:
Local $a = $dict.Item("foo")
_ArrayAdd($a, "world")
$dict.Item("foo") = $a
Related
this question succeeds the following question: Moose: Array of Objects->loop through Attribute
I'm struggling to implement the grep syntax into a List::Compare Object:
my #aIdentList=("z003","t302","p032");
my $lc=List::Compare->new('-u',\#aIdentList,\#{(grep {$_->Identifier}#aArray1)});
my #unique=$lc->get_unique;
\#{(grep {$_->Identifier}#aArray1)}
This part is weird. You are trying to dereference a list via #{}. That doesn't work.
The grep returns a list already. You do not need to use parenthesis () to construct a new list. Perl will ignore them. Then your #{} is simply wrong. You need a new array reference. That's []. It will construct a new array ref from the list that grep returns. That's already enough to pass to List::Compare->new. The backslash \ is only needed if you want to take a reference of something, but you now already have a reference.
But you actually do not want to grep here. You want to map!
This is what your code should look like.
List::Compare->new( '-u', \#aIdentList, [ map { $_->Identifier } #aArray1 ] )
grep will filter out every element of the list you pass in where the block does not return a true value. Since all objects in #aArray1 (typing this is horrible!) have an Identifier property, this will let all elements through. The second array ref arg to new will then be a list of objects. That's not what you want, because you'd be comparing apples to oranges.
Instead, you need to use map, which will pass the return value of the block for each element. It's like an inline foreach loop. Then your second list will be the actual identifiers of the objects, and not the objects themselves.
Why is my array globally manipulated, when I run the below ruby code? And how can I get arrays to be manipulated only within the function's scope?
a = [[1,0],[1,1]]
def hasRowsWithOnlyOnes(array)
array.map { |row|
return true if row.keep_if{|i| i != 1 } == []
}
false;
end
puts a.to_s
puts hasRowsWithOnlyOnes(a)
puts a.to_s
$ ruby test.rb output:
[[1, 0], [1, 1]]
true
[[0], []]
I can't get it to work. I've even tried .select{true} and assign it to a new name. How does the scope work in Ruby for Arrays?
Just for reference, $ ruby -v:
ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-linux]
It's not a scope problem, it's an argument passing problem
All variables in Ruby are references to objects.
When you pass an object to a method, a copy of that object's reference is made and passed to the object.
That means that the variable array in your method and the top-level variable a refer to the exact same Array. Any changes made to array will be also visible as changes to a, since both variables refer to the same object.
Your method does modify the array by calling Array#keep_if. The keep_if method modifies the array in-place.
The fix
The best fix for this is to make it so that your method does not modify the array that was passed in. This can be done pretty neatly using the Enumerable#any? and Enumerable#all? methods:
def has_a_row_with_only_ones(array)
array.any? do |row|
row.all? { |e| e == 1 }
end
end
This code says that the method returns true if, for any row, every element in that row is 1. These methods do not modify the array. More important, they communicate the method's intent clearly.
The poor workaround
If you want the method to act as through a copy of the array were passed to it, so that the array can be modified without that modification being visible outside the method, then you can make a deep copy of the array. As shown in this answer, you can define this method to make a deep copy:
def deep_copy(o)
Marshal.load(Marshal.dump(o))
end
Then, at the top of the method, make the deep copy:
def has_a_row_with_only_ones(array)
array = deep_copy(array)
# code that modifies array
end
This should be avoided because it's slow.
Ruby is pass by value
Via sitepoint
Ruby has variables defined within different scopes, which you probably
know already. I found that most tutorials describe them briefly (the
variable types), but they fail to mention precisely what their scope
is.
Here are the details:
Class variable (##a_variable): Available from the class definition and any sub-classes. Not available from anywhere outside.
Instance variable (#a_variable): Available only within a specific object, across all methods in a class instance. Not available directly from class definitions.
Global variable ($a_variable): Available everywhere within your Ruby script.
Local variable (a_variable): It depends on the scope. You’ll be working with these most and thus encounter the most problems, because their scope depends on various things.
I have a class of objects known as blocks. Currently, I am creating an array of blocks using a for loop by simply tacking them unto an empty array
blockArray=[];
for ii=1:Size
blockArray=[blockArray block(....)];
end
In order to preallocate memory, how do I initialize an object array of blocks with dummy values?
For instance if instead of using block objects I used numbers, I could easily preallocate by using zeros(1,Size). Is there something similar that I could do?
The matlab documentation describes
To preallocate the object array, assign the last element of the array first. MATLAB® fills the first to penultimate array elements with default DocArrayExample objects.
So, to do this, instead of iterating over from 1:size, it is simpler to do...
blockArray = []
blockArray(size) = block(...)
The language does not really support this, there exists multiple solutions (or workarounds).
Replicating the first instance
When pushing the first element into the array, you can fill the whole array with this element to achieve a preallocation. This might look very bad, but it is actually the fastest possibility known to me.
for ii=1:S
%assumption e is a scalar, otherwise the code is totally screwed
e=block(....)
if ii==1
%to do preallocation, fill it with your first element
blockArray(1:S)=e
else
blockArray(ii)=e
end
end
Use cell arrays
Obvious simple solution, you can put any class into the fields
blockArray=cell(S,1);
for ii=1:S
%assumption e is a scalar, otherwise the code is totally screwed
e=block(....)
blockArray{ii}=e
end
This solution is very simple but slower than the first. You also lose some functionality which is not available for cell arras
Let your class implement array functionality
classdef A
properties
arg1
out
end
methods
function obj = A(varargin)
if nargin==0
%null object constructor
elseif strcmpi(varargin{1},'createarray')
sz=varargin(2:end);
%preallocate
obj(sz{:})=A;
else
%standard constructor
obj.arg1=varargin{1};
obj.out=[1 2 3;];
end
end
end
end
Constructor with no input argument creates an "empty" or "null" object, this is used to preallocate so it should be empty.
Constructor with first parameter makearray creates an array
Otherwise your constructor should be called.
Usage:
%create an empty object
A
%create an array of size 2,3,4
A('createarray',2,3,4)
%use the standard constructor
A(2)
Biggest downside is you have to modify your classes. Never tested this solution, but it should be close to the first in performance.
I basically want to write logic such that if certain element is already present in array i dont want to again put it into it. My array is one dimensional. I am not able to understand how filter function works. Please help. Thanks.
I'm not sure I exactly get what you are trying to do.
But what I understand makes me recommend you to use Dictionary (it is basically a Hashmap)
It works with keys and values.
Each element of this Dictionary contains a unique key (a String that is used to access specifically the data you want) and a value attached to it (can be a String, a Number...)
Here is how to use it :
in your VBA page, go to Tools -> References -> add "Microsoft Scripting Runtime" from the list of available references.
Then in your code :
Dim myDico as Dictionary
set myDico = new Dictionary
myDico.add "myKey", 5
msgbox myDico.Item("myKey") '5
I have an array in a perl hash declared like this:
my %updatevars = (datapoints => []);
I'm later trying to add elements to it like this:
push($updatevars{'datapoints'}, [$updatestart+$i, $bandwidth]);
I get this error:
Type of arg 1 to push must be array (not hash element) at dirlist.pl line 61, near "])"
Hashes (and arrays) can only contain scalars. That's why we must put reference to arrays (and hashes) in them. $updatevars{datapoints} contains a reference to an array. As such, you need to use
push #{ $updatevars{datapoints} }, [ $updatestart+$i, $bandwidth ];
Note that your code would work on 5.14+ as push was changed to also accept a reference. (This change is "considered highly experimental" however, so you should use the above code in newer versions too.)
$updatevars{'datapoints'} is an array ref, as you assigned it: []. push takes an array as argument, not an array reference. So you need to dereference your reference:
push #{ $updatevars{'datapoints'} }, ...
In Perl v5.14, you may use a reference, as noted in the documentation. But it does not sound like it is a recommended practice just yet.
Starting with Perl 5.14, "push" can take a scalar EXPR, which must
hold a reference to an unblessed array. The argument will be
dereferenced automatically. This aspect of "push" is considered highly
experimental. The exact behaviour may change in a future version of
Perl.
Try this:
push #{$updatevars{'datapoints'}}, [$updatestart+$i, $bandwidth];
Since push takes an array and $updatevars{'datapoints'} is an array reference, you have to de-reference it by putting the #{} in front.