I'd like to auto handle array out of bounds index access by giving 0 instead.
But what I have now is code like
evenIndexNext = 2*j+1 + 2*i ;
oddIndexPrev = 2*j+1 - i ;
evenValueNext = 0 ;
oddValuePrev = 0 ;
if( evenIndexNext <= n )
evenValueNext = s( evenIndexNext ) ;
end
if( oddIndexPrev >= 1 )
oddValuePrev = s( oddIndexPrev ) ;
end
Where s is the array. A bit clunky.
Maybe, you could do:
try
evenValueNext = s( evenIndexNext ) ;
catch
evenValueNext=0;
end
or, you could define a function to do that:
function y=checkBound(l,i)
if (i<1) || (i>numel(l))
y=0;
else
y=l(i);
end
end
evenValueNext = checkBound(s,evenIndexNext);
oddValuePrev = checkBound(s,oddIndexPrev) ;
You could define a new class to handle this. If you overloaded the subsref method of the class, you could tell it to check if the index was out of bounds, and return 0 if that was the case.
Related
I'm having a bit of trouble iterating through a few if statements more than eight times. The code seems to work fine for the first several comparisons, performs the arithmetic and return/saves the output row 'export_data'. However, after that, it only returns the else condition and response. The variables beings assessed have 1500 rows each. I've added the code below and two photos showing the outputs. Any insight will be very much appreciated.
function [export_data] = WS_Zones(Forecast_WS, Observed_WS)
if (Forecast_WS > Observed_WS)
WS_Zone_1 = Observed_WS.*1.24;
WS_Zone_2 = Observed_WS.*1.28;
elseif (Forecast_WS < Observed_WS)
WS_Zone_1 = Observed_WS.*0.76;
WS_Zone_2 = Observed_WS.*0.72;
else
WS_Zone_1 = Observed_WS;
WS_Zone_2 = Observed_WS;
end
export_data=[Forecast_WS Observed_WS WS_Zone_1 WS_Zone_2];
filename = 'testdata.xlsx';
sheet = 1;
xlRange = 'A1';
xlswrite(filename,export_data,sheet,xlRange)
end
Expected Output
Wrong Output
This statement:
if [1 2 3] > [1 1 1]
disp('hello');
end
will never print "hello" even though 2 and 3 are both greater than 1. This is because the if statement needs to evaluate to either scalar true or false. If a vector is used, than only the first element is used to determine if the statement is true or not (comparisons between other elements are ignored). You can use any and all if you want to apply conditions on all elements.
If Forecast_WS and Observed_WS aren't scalars then you need to wrap your if statement in a for loop, e.g.:
WS_Zone_1 = Observed_WS;
WS_Zone_2 = Observed_WS;
for i = 1:numel(Forecast_WS)
if Forecast_WS(i) > Observed_WS(i)
WS_Zone_1(i) = Observed_WS(i).*1.24;
WS_Zone_2(i) = Observed_WS(i).*1.28;
elseif Forecast_WS(i) < Observed_WS(i)
WS_Zone_1(i) = Observed_WS(i).*0.76;
WS_Zone_2(i) = Observed_WS(i).*0.72;
end
end
or vectorize it using logical indexing:
WS_Zone_1 = Observed_WS;
WS_Zone_2 = Observed_WS;
idx = (Forecast_WS > Observed_WS);
WS_Zone_1(idx) = Observed_WS(idx).*1.24;
WS_Zone_2(idx) = Observed_WS(idx).*1.28;
idx = (Forecast_WS < Observed_WS);
WS_Zone_1(idx) = Observed_WS(idx).*0.76;
WS_Zone_2(idx) = Observed_WS(idx).*0.72;
I am using matlab. I have a function which at the moment returns 5 arrays, but I want to join the array into a single matrix or just a cell array with heading of each being the output of the current function?
For instance, giving output like:
low_sec lowmid_sec
1 7
2 6
35 5
5 43
Any ideas?
function [low_sec ,lowmid_sec , middle_sec , upmid_sec , upper_sec]= sepfunc(intensdata)lengthofdata=length(intensdata);
count1=0;
count_2=0;
count_3=0;
count_4=0;
count_5=0;
for i= 1:lengthofdata %loop to seperate count number of data in 5 groups
if (intensdata(i,1)<0.05)
count1=count1+1;
elseif (intensdata(i,1)>=0.05 && intensdata(i,1)<0.1)
count_2=count_2+1;
elseif (0.1<=intensdata(i,1) && intensdata(i,1)<0.15)
count_3=count_3+1;
elseif (0.15<=intensdata(i,1) && intensdata(i,1)<0.2)
count_4=count_4+1;
elseif (intensdata(i,1)>=0.2 )
count_5=count_5+1;
end
end
disp(count1);
disp(count_2);
disp(count_3);
disp(count_4);
disp(count_5);
j=1;
k=1;
m=1;
n=1;
x=1;
low_sec=[count1];
lowmid_sec=[count_2];
middle_sec=[count_3];
upmid_sec=[count_4];
upper_sec=[count_5];
for i= 1:lengthofdata %to seperate original data into 5 different sub-groups.
if (intensdata(i,1)<0.05)
low_sec(j,1)=intensdata(i,1);
j=j+1 ;
elseif(0.05<=intensdata(i,1) && intensdata(i,1)<0.1)
lowmid_sec(k,1)=intensdata(i,1);
k=k+1;
elseif(0.1<=intensdata(i,1) && intensdata(i,1)<0.15)
middle_sec(m,1)=intensdata(i,1);
m=m+1;
elseif(0.15<=intensdata(i,1) && intensdata(i,1)<0.2)
upmid_sec(n,1)=intensdata(i,1);
n=n+1;
elseif( intensdata(i,1)>=0.2)
upper_sec(x,1)=intensdata(i,1);
x=x+1;
end
end
You have a few options, ues a cell array as you mentioned, use the new table structure or the easiest would be to just create a struct.
To do this, all you need is to add the following at the end of your function:
sec.low = low_sec;
sec.lowmid = lowmid_sec;
sec.middle = middle_sec;
sec.upmid = upmid_sec;
sec.upper = upper_sec;
and then to change your first line to be:
function sec = sepfunc(intensdata)
I'm getting a very irritating error whenever I do anything like this with arrays. I have code that sets up the array in the love.load() function:
function iceToolsInit()
objectArray = {} --for object handling
objectArrayLocation = 0
end
and then code that allows for the creation of an object. It basically grabs all of the info about said object and plugs it into an array.
function createObject(x, y, renderimage) --used in the load function
--objectArray is set up in the init function
objectArrayLocation = objectArrayLocation + 1
objectArray[objectArrayLocation] = {}
objectArray[objectArrayLocation]["X"] = x
objectArray[objectArrayLocation]["Y"] = y
objectArray[objectArrayLocation]["renderimage"] =
love.graphics.newImage(renderimage)
end
After this, an update function reads through the objectArray and renders the images accordingly:
function refreshObjects() --made for the update function
arrayLength = #objectArray
arraySearch = 0
while arraySearch <= arrayLength do
arraySearch = arraySearch + 1
renderX = objectArray[arraySearch]["X"]
renderY = objectArray[arraySearch]["Y"]
renderimage = objectArray[arraySearch]["renderimage"]
if movingLeft == true then --rotation for rightfacing images
renderRotation = 120
else
renderRotation = 0
end
love.graphics.draw(renderimage, renderX, renderY, renderRotation)
end
end
I of course clipped some unneeded code (just extra parameters in the array such as width and height) but you get the gist. When I set up this code to make one object and render it, I get this error:
attempt to index '?' (a nil value)
the line it points to is this line:
renderX = objectArray[arraySearch]["X"]
Does anyone know what's wrong here, and how I could prevent it in the future? I really need help with this.
It's off-by-one error:
arraySearch = 0
while arraySearch <= arrayLength do
arraySearch = arraySearch + 1
You run through the loop arrayLength+1 number of times, going through indexes 1..arrayLength+1. You want to go through the loop only arrayLength number of times with indexes 1..arrayLength. The solution is to change the condition to arraySearch < arrayLength.
Another (more Lua-ly way) is to write this as:
for arraySearch = 1, #objectArray do
Even more Lua-ly way is to use ipairs and table.field reference instead of (table["field"]):
function refreshObjects()
for _, el in ipairs(objectArray) do
love.graphics.draw(el.renderimage, el.X, el.Y, movingLeft and 120 or 0)
end
end
objectArray and movingLeft should probably be passed as parameters...
I have an array:
step1 = [0,0;
0,1;
1,1;
2,3;
3,4;
3,5;
3,6;
3,7;
4,7;
5,7;
6,7;
6,6;
6,5;
6,4;
6,3;
6,2;
5,1];
I want to step through this array and create new arrays for the row and column that increment by 0.1 from one row to another. This is what I did:
z=1;
u=length(step1);
step_b4X = zeros(u,1);
step_b4Y = zeros(u,1);
while z <= length(step1)
step_b4X = step_presentX;
step_presentX(z,1) = step1(z,1);
step_b4Y = step_presentX;
step_presentY(z,1) = step1(z,2);
pathX = step_b4X:0.1:step_presentX;
pathY = step_b4Y:0.1:step_presentY;
z = z+1;
end
I get zeros.
I want pathX = 0:0.1:0....pathY = 0:0.1:1
next pathX = 0:0.1:1....pathY = 1:0.1:1... and so on
If you do
start:increment:end
where start == end, you'll get a scalar equal to start (which is logical).
If you want pathX and pathY to have the same length at each iteration, you'll have to do this:
z = 1;
while z <= length(step1)
currentX = step(z,1); nextX = step(z+1,1);
currentY = step(z,2); nextY = step(z+1,2);
pathX = currentX : 0.1 : nextX;
pathY = currentY : 0.1 : nextY;
if numel(pathX) == 1
pathX = repmat(pathX, numel(pathY),1); end
if numel(pathY) == 1
pathY = repmat(pathY, numel(pathX),1); end
z = z+1;
end
Now you'll have the right arrays at each iteration, that you'll use directly or save in a cell-array for later. If you want everything in one big array, add this to the end of the loop:
pathX_final = [pathX_final; pathX];
pathY_final = [pathY_final; pathY];
and initialize them as empty before the loop, of course.
Alternatively (much cleaner and possibly a bit faster), ditch the whole loop and use interp1:
x = step1(:,1);
y = step1(:,2);
xx = interp1(1:numel(x), x, 1:0.1:numel(x));
yy = interp1(1:numel(y), y, 1:0.1:numel(y));
I have a small perl script that needs to evaluate the equality of two parameters and a small return from the database.
my ($firstId, $secondId, $firstReturnedId, $secondReturnedId, $picCount);
my $pics = $dbh->prepare(qq[select id from pictures limit 10]);
$firstId = q->param('firstId');
$secondId = q->param('secondId');
$pics->execute or die;
my $picids = $pics->fetchall_arrayref;
$picCount = scalar(#{$picids});
$firstReturnedId = $picCount > 0 ? shift(#{$picids}) : 0;
$secondReturnedId = $picCount > 1 ? pop(#{$picids}) : $firstReturnedId;
Here, a quick look at my debugger shows that $picCount = 1 and $firstReturnedId = 9020 and $secondReturnedId = 9020. However, they are both denoted as
ARRAY(0x9e79184)
0 9020
in the debugger so when I perform the final check
my $result = (($firstId == $firstReturnedId) && ($secondId == $secondReturnedId)) ? 1 : 0;
I get $result = 0, which is not what I want.
What am I doing wrong?
DBI::fetchall_arrayref returns a reference to a list of "row results". But since there could be more than one value in a row result (e.g., your query could have been select id,other_field from pictures), each row result is also a reference to a list. This means you have one more dereferencing to do in order to get the result you want. Try:
$picCount = scalar(#{$picids});
if ($picCount > 0) {
my $result = shift #{$picids};
$firstReturnedId = $result->[0];
} else {
$firstReturnedId = 0;
}
if ($picCount > 1) {
my $result = pop #{$picids};
$secondReturnedId = $result->[0];
} else {
$secondReturnedId = $firstReturnedId;
}
or if you still want to use a concise style:
$firstReturnedId = $picCount > 0 ? shift(#{$picids})->[0] : 0;
$secondReturnedId = $picCount > 1 ? pop(#{$picids})->[0] : $firstReturnedId;