If and elseif, only the first line work? - matlab

L=1; Nx=51; PeriodicFlag=1; T=15; Nt=51;
spacedef='Pade6FirstDeriv'; casedef='LinearAdvection';
if (spacedef == 'Pade6FirstDeriv')
D1 = sparse(Pade6(Nx,dx,PeriodicFlag));
elseif (spacedef == 'Upwind3FirstDeriv')
D1 = sparse(Upwind3(Nx,dx,PeriodicFlag));
elseif (spacedef == 'Central4FirstDeriv')
D1 = sparse(Central4(Nx,dx,PeriodicFlag));
elseif (spacedef == 'Central2FirstDeriv')
D1 = sparse(Central2(Nx,dx,PeriodicFlag));
else
error(sprintf('Unknown spacedef = %s',spacedef));
end
In the above code, the if section is a small segment from a function I've constructed. I'm trying to get the function to know which methods to use based on my input (spacedef). Central2, Central4, Upwind3, and Pade6 are other functions I've written. The weird thing is that when spacedef =/= to 'Pade6FirstDeriv', I would get an error stating Error using ==, Matrix dimensions must agree. I've tried swapping the order of the if loop (by placing Central4, Central2, Pade6, and Upwind3 in the first line of the loop), and it seems like only the top line of the loop will work (the elseifs are not working). I'd greatly appreciate it if anybody can help me out. Thanks!

As has been noted in the comments, this is a common error when people first start comparing strings in MATLAB, and strcmp or strcmpi is generally the solution.
However, one solution the questions links in the comments don't present, and a solution I think looks much nicer, is the switch statement:
switch (spacedef)
case('Pade6FirstDeriv')
D1 = sparse(Pade6(Nx,dx,PeriodicFlag));
case('Upwind3FirstDeriv')
D1 = sparse(Upwind3(Nx,dx,PeriodicFlag));
case('Central4FirstDeriv')
D1 = sparse(Central4(Nx,dx,PeriodicFlag));
case('Central2FirstDeriv')
D1 = sparse(Central2(Nx,dx,PeriodicFlag));
otherwise
error(sprintf('Unknown spacedef = %s',spacedef));
end
Note: if I expect others to use my code with string comparisons, I usually lower the input such that the comparison is case-insensitive, although I have not done that here.

Related

Insert a number before a given number in a linked list

I'm doing an introduction course in programing in matlab and python and I have only been coding for a short time, so I'm still on the basics.
In the problem that I'm trying to solve, we have been given a code that creates a linked list by the teacher.
classdef Elem < handle
%Elem A class realising a linked list.
properties
data
next = Elem.empty
end
methods
function node = Elem(value)
if (nargin > 0)
node.data = value;
end
end
function obj = insert(obj, value)
if(isempty(obj.next))
obj.next = Elem(value);
else
obj.next.insert(value);
end
end
% More methods go here
end
end
One of the questions is then to make a code that can insert a number before a number in the linked list.
To do this I have made this code.
function newlist=InsertBefore(list,newdata,dataBefore)
if ~isempty(list)
if list.data==dataBefore
newlist = Elem(newdata);
newlist.next = list;
elseif list.next.data==dataBefore
newlist=list;
newelem = Elem(newdata);
newelem.next = list.next;
newlist.next = newelem;
else
InsertBefore(list.next,newdata,dataBefore)
end
end
end
If I then write
linkedlist2=InsertBefore(LinkedList,4,12)
the function makes a new list with 4 in front of the 12 which is the first number in the list. so the "If" part of the code works fine. if I try doing the same thing with a number in the middle of the list it says.
Output argument "newlist" (and maybe others) not assigned during call to "InsertBefore".
I have tried many things but nothing has really worked perfect yet, so your help is much appreciated
Thanks
Lasse
SOLVED
Had to have
else
newlist = InsertBefore(list.next,newdata,dataBefore)

special compare in MATLAB

Hi I'm trying to achieve this:
for i=1:maxaps
for j=1:length(num2)
**if (isequal(sortedCell(i),txt2(j)) && sortedCell(i)~=0)** %important line
rssi2sorted(i)=rssi2(j); %I don't think we need matching part
break;
end
end
end
and I receive this error:
??? Undefined function or method 'ne'
for input arguments of type 'cell'.
Error in ==> sortingmethod at 116
if
(isequal(sortedCell(i),txt2(j))
&& sortedCell(i)~=0)
if I try like this:
for i=1:maxaps
for j=1:length(num2)
**if (isequal(sortedCell{i},txt2(j)) && sortedCell(i)~=0)** %important line
rssi2sorted(i)=rssi2(j); %I don't think we need matching part
break;
end
end
end
the elements can't be compared because of the format:
>> sortedCell{1}
ans =
00:1e:58:f4:15:f7
>> txt2(6)
ans =
'00:1e:58:f4:15:f7'
any recommendations on how to fix this?
Thanks!
I believe that the issue is actually with this part (the ne that your error refers to):
sortedCell(i)~=0
You're comparing a cell, rather than its contents, to zero. You should use:
sortedCell{i}~=0
EDIT:
If the question is not about the error message, but rather how to compare strings, just use strcmp (never use ==, eq, or isequal to compare strings):
if strcmp(sortedCell{i},txt2(j))
...
end
I don't know what the && sortedCell{i}~=0 part you've added is for, but you can add it back if needed.
strcmp also take cell arrays as inputs (see the documentation) so you may be able to get rid of on of your for loops. I don't know what your code does, but maybe you you could use something like this:
for j=1:length(num2)
c = strcmp(sortedCell,txt2(j));
if any(c)
rssi2sorted(c)=rssi2(j);
break;
end
end
use strcmp (of strcmpi ignoring case) to test is strings are the same, isequal is for testing if values are numerically equal. e.g.
if ( strcmp(sortedCell{i},txt2(j)) && sortedCell(i)~=0 )

Error using minus in MATLAB

temp(i,1) = rand(1)*(pb(1,num).pos(i,1) - pw(1,num).pos(i,1));
This line gives the following error:
Error using ==> minus
Not enough input arguments.
The following are the definitions of pb and pw.
pw=struct('fitness',[],'pos',{});
pb=struct('fitness',[],'pos',{});
pos is a 2 x 1 array.
When tracking down errors like this, I break the problem up into smaller bits. Especially when the logic isn't readily apparent. Not only does it provide a path that can be used to step through your function using the debugger, but it also makes it more readable.
I've taken liberty with the intermediate variable names.
thisPb = pb(1,num);
thisPw = pw(1,num);
initialPos= pw.pos(i,1);
finalPos = pb.pos(i,1);
whos initialPos finalPos
temp(i,1) = rand(1) * (finalPos - initialPos);
The line with whos will print out the values. Make sure that finalPos and initialPos are both numbers.
One way that you can get this error is when num is an empty matrix.
The expression
>> s(x).a
can return a variable number of outputs, depending on the size of x.
If x = [1,2,3] for example, it will return three values (as long as s has at least three elements).
If x = [] on the other hand, then s(x).a will return no outputs, so the expression
>> disp(s(x).a)
will give you a Not enough input arguments error, which is almost certainly what you're seeing. You should check that num is not empty.
Are you sure, that all values are really initialised? Try to check this before your codeline.
disp(pb(1,num).pos(i,1))
disp(pw(1,num).pos(i,1))
temp(i,1) = rand(1)*(pb(1,num).pos(i,1) - pw(1,num).pos(i,1));

IDL equivalent of MATLAB function accumarray()

I've been given the task of translating a piece of MATLAB code into IDL and have
hit a roadblock when I came across the MATLAB function accumarry(). The
function, described here
is used to sum elements in one array, based on indices given in another. Example
1 perhaps explains this better than the actual function description at the top
of the page. In trying to reproduce Example 1 in IDL, I haven't been able to avoid a for loop, but I'm confident that it is possible. My best attempt is the following:
vals = [101,102,103,104,105]
subs = [0,1,3,1,3]
n = max(subs)+1
accum = make_array(n)
for i = 0, n-1 do begin
wVals = where(subs eq i,count)
accum[i] = count eq 0 ? 0 : total(vals[wVals])
endfor
print,accum
; 101.000 206.000 0.00000 208.000
Any advice on improving this would be greatly appreciated! I expected IDL to have a similar built-in function, but haven't been able to track one down. Perhaps some magic with histogram binning?
I found a number of possible solutions to this problem on Coyote's IDL site (not surprisingly.)
http://www.idlcoyote.com/code_tips/drizzling.html
I ended up using the following, as a compromise between performance and readability:
function accumarray,data,subs
mx = max(subs)
accum = fltarr(mx+1)
h = histogram(subs,reverse_indices=ri,OMIN=om)
for j=0L,n_elements(h)-1 do if ri[j+1] gt ri[j] then $
accum[j+om] = total(vals[ri[ri[j]:ri[j+1]-1]])
return,accum

Switching even- and odd-indexed characters in Matlab

Using Matlab, write a function called tripFlip that takes in one string and switches each even-indexed charactar with the odd-indexed character immediately preceding it. Use iteration. Example: tripFlip('orange') ->'ronaeg'
I assume this is homework, so I won't give a complete answer. You can use double to convert a string to an array, and char to go back, if working with arrays makes the problem any easier. Otherwise, strings seem to work just like arrays in terms of indexing: s(1) gets the first character, length(s) gets the length, etc.
I agree its a homework question, and posting it here will only bite you back in the long run. But here goes:
a = 'orange';
b = '';
b(2:2:length(a))= a(1:2:end);
b(1:2:length(a))= a(2:2:end);
disp(b)
In one line:
>> input = 'orange';
>> output = input(reshape([2:2:end;1:2:end],1,[]))
output =
ronaeg
It's not a function and doesn't use iteration, but it's how you'd solve this if you were to learn Matlab.
Something like this should do the trick, perhaps you want to make it a bit more robust.
function b = TripFlip(a)
a = 'orange';
b = '';
for i = 2:2:length(a)
b=[b a(i) a(i-1)]
end