I'm trying so hard to initialize an array or arrayList of strings from a file while using a loop, but every function I'm using- put/enter/force nothing seems to work. the array time after time got filled with the last string I read even though I'm accessing a specific index that I increasing every iteration.
(I tried to add regular constant string and it worked well, I don't understand the difference.
Thanks to everyone who would help.
tArray:ARRAY[STRING] -- declaring
create tArray.make_empty
readingFile() --function
local
k:INTEGER_32
do
from k:=0
until curFile.end_of_file
loop
curFile.read_line
curLine:=curFile.last_string
tArray.force (curLine, k)
--tArray.put(curLine, k)
--tArray.enter (curLine, k)
--tArray.at (k):=curLine
--tArray.force ("sara", k+1)
k:=k+1
end
end
The feature read_line does not create a new string object every time, but rather reuses the last one. In other words, last_string always refers to the same object. The solution is to use a clone of the object associated with last_string at every iteration:
curLine := curFile.last_string.twin
Related
I'm learning Ruby and have been practicing by solving problems on Codewars and Leetcode. I've come across this problem in Leetcode where it is asking me to, given an array and a value, modify the array in place by removing an occurrence of the value given in the array. Pretty simple! I was able to solve it- but, this curious thing happened and I don't know why!
Here's my code:
def remove_element(nums, val)
nums.each_with_index do |num, index|
if num == val
nums[index] = nil
end
end
nums.compact!
nums.length
end
You can see here that on line 4 I've written "nums[index] = nil", and this worked just fine for me. However, for the longest time I was trying to solve the challenge by writing "num = nil". What doesn't make sense to me is, why does "nums[index]" work and not "num"? Don't they refer to the same thing?
Answer from Dave Newton:
num is a block-local variable, nums is the array. Modifying a local parameter is different than accessing a reference. As another example, say that the array was filled with objects. num.some_property = 5 would modify the property of the array entry, num = SomeNewObject.new would just create a new object and not modify the array entry. Same thing would happen if you were calling a function.
I have this function where I use an array as a FIFO queue (i.e., put elements in it and process them using a first-in first-served approach). In particular, I call this array a MsgQueue as it holds messages.
The MsgQueue is used when a new msg is sent (event), which triggers the execution of the handleMsgSent() method, which I show next
function handleMsgSent(this, msg)
this.MsgQueue = [this.MsgQueue msg];
while(numel(this.MsgQueue) > 0)
m = this.MsgQueue(1);
this.MsgQueue = this.MsgQueue(2:end); % <----- OPTION A
% DO WHATEVER WITH THE MESSAGE
%this.MsgQueue(1) = []; % <------ OPTION B
end
end
As you can see I have marked the code with OPTION A and OPTION B comment. So, the point is option B ends up with the "Matrix Index is out of range for deletion" error while option A works (apparently) perfectly fine, with no errors.
Can anyone help me to understand the difference? Well, I understand that option A is not deleting anything but just "discarding" the first element of the array but, why does option B fails in deleting if there is at least one element in MsgQueue?
For an empty array, end is 0. If you check the documentation for the colon operator, for start>end it returns an empty array. Thus, the first option deletes noting in some cases while the second option always indexes the second element.
After debugging my code I seem to have realised of the reason. In my code there is a comment:
% DO WHATEVER WITH THE MESSAGE
The problem was that at this point I was invoking another method that triggered new messages to be sent and thus entering the handleMsgSent() method again. Thus, when I modify the MsgQueue before that I have no problems but when I do it afterwards I get into trouble.
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've been creating a system for storing objects that persist for a specified duration, then remove themselves. However, I'm having some trouble figuring out how to remove expired items from the array while the for loop is running (to minimize extra iterations through the array)
Here is what I've made so far. Terms in the list are flagged with a Boolean value indicating that they're done.
For i = 0 To VisualEffects.Count - 1 Step 1
VisualEffects(i).Update(gt)
VisualEffects(i).Draw(sb, Pos, Cam)
If VisualEffects(i).CD.isExpired() Then
VisualEffects.RemoveAt(i)
i = -1
End If
Next
Why does this produce an error? How can I remove a term from an array and continue iterating through the remainder of the loop?
Regards
Ares
The line
i = -1
sets i to -1, causing the For loop to terminate.
If you can, reverse the order of the loop so that you start with the last array element and count down. That makes the remove logic much more straightforward.
.NET arrays are fixed-size so you can't actually remove an element from an array at all. You can change the value of an element, so you can set an element to Nothing to remove the object that it referred to, but the element is still there. If you read the MSDN documentation for the Array class, you'll see that the RemoveAt method throws a NotSupportedException for this reason.
If you're actually using a collection rather than an array then you can call RemoveAt but you need to loop from the last index to the first rather than first to last. That way, removing an item will not affect the indexes of those items that you are yet to visit.
I am working with an older and undocumented set of ActionScript (AS2) and I have found that an array, when looping through it the second time, does not give the proper results. It has been a while since I used ActionScript - does the array need to be reset before the second time through another for loop?
For instance PHP has reset() which returns the array's pointer back to the first item in the array.
There's is no such thing as pointers in ActionScript.
You can target each and every item in an Array by simply targeting it with myArray[index], and no pointer needs to be reset to be able to re-read it.
If your two loops produce different results, I would suggest looking into code that could change anything in it between the two loops or in the first one.
Maybe you could post it here ?