What is wrong with this for loop command in MATLAB (excluding an index) - matlab

I am trying to exclude an index within a for loop. I can't understand why the following code keeps bringing up an error:
for(l=1:Nmax, l~=m)
The error is
Error: File: BARW2Dwithducts.m Line: 76 Column: 24
Unbalanced or unexpected parenthesis or bracket.
I don't see how the expression is unbalanced (the code itself works fine and is error free if I just use for l=1:Nmax, but this doesn't give me what I need...

To skip an index, your typical option is to put the following inside the loop (as the first thing):
if (l == m)
continue
end
Another option is to generate all indices, then remove the target one:
allInds = 1:Nmax;
allInds(allInds == m) = []; % remove index m.
for l = allInds
...
This has a nice advantage that you can clearly see all the indices that will be visited before the loop even starts, and as you start adding extra conditions this one scales much better than a horrible nest of conditions inside the loop.

One way to skip the value m is to do as follows:
for l=[1:m-1,m+1:Nmax]
% ...
end
Note that this will not work if m-1>Nmax, as you will visit values larger than Nmax.

Related

Index out of bounds after reading a text file

I have the following simple code, and I tried to use one of the indices from the .txt file. The index that I want is at (4,1) while the size of my matrix in the .txt file is (8,4). When I run the code, MATLAB give me the following error;
Attempted to access q(4,1); index out of
bounds because size(q)=[1,601]
Can someone help me understand why I receive the error and how to fix it?
Here is the code:
q = fileread('sv11edit.txt');
toe = q(4,1)
The answer will depend on the format of the file sv11edit.txt. However, fileread returns a string of characters. In this case, it gives you a string that is 601 characters long. You receive an error because you assume that q is 8 by 4, but this is not the case.
Check what is being stored in q before you try anything like the second line of your code. The function load may be a better alternative to fileread.

How to read different lines from a text file simultaneously

I need to read a file line by line such that it reads the first line, does something with it, then takes the second line, does something with it and so on.
I know how to read a text file line by line:
for(line <- Source.fromFile("file.txt").getLines())
{
insert(line) **Use the first line of the file in this function
reverse(line) **Use the second line of the file in this function
}
in the insert function, first I want to use the first line of the file, and in the reverse function I want to use the second line, then in the second iteration of the loop, I want to use the 3rd line in the insert function and the 4th line in the reverse function and so on. How to do that?
EDIT: This is just an example. I want a general thing, like suppose if I want to use the first line, second line, third line and then iterate the for loop, how to do that?
Lots of clever solutions. Here's a simple one using zipWithIndex that handles even cases with an uneven number of lines.
for((line,index) <- Source.fromFile("file.txt").getLines().zipWithIndex)
{
if (index % 2 == 0) insert(line)
else reverse(line)
}
One more approach, using grouped, which takes into account a (possibly) uneven number of lines,
Source.fromFile("file.txt")
.getLines
.grouped(2)
.map { xs => (xs.head, xs.last.reverse) }
Note that getLines gives an iterator for fetching one line at a time, sequentially, then grouped gives yet another iterator with paired lines for simultaneous processing. This is in contrast with reading multiple lines of a file at the same time.
Using sliding to group your lines into pairs of two.
for(pairs <- Source.fromFile("file.txt").getLines().sliding(2, 2)) {
insert(pairs.head)
reverse(pairs.last)
}
Obviously you'll need to handle the condition where you don't have a list of even length.

Control flow within an eval function in Matlab

If I include a continue as a parameter of an eval() instruction, it does not work as expected. For example, when executing the following code:
listParam = {'a','b','c'};
a = 17;
b = NaN;
c = 4;
for ii=1:numel(listParam),
eval(['if isnan(',listParam{ii},'), continue; end']);
disp(['The parameter ', listParam{ii}, ' is not a NaN.']);
end
It will prompt the error:
Error: A CONTINUE may only be used within a FOR or WHILE loop.
Anybody knows why?
Note: I know that I should avoid eval() and the previous example could be refactored in a much better coding; but I found a weird behaviour and I am curious what is happening.
The expression you pass to eval must be a valid matlab expression on it's own, any surrounding code is not considered. This means each continue must be surrounded by a loop. Either put the surrounding for within your eval or put the continue outside.
As #Daniel has pointed out, eval is called by the script, while it is not directly controlled by the for loop. You can think it as: the continue in eval would move the program counter to the head of the code inside eval, but not that of the for loop; this of course would fail, as Matlab does not allow jumping between lines.
A continue can only appear directly inside a for or while loop. However, you can hack the code like this:
for ii=1:numel(listParam),
eval(['if isnan(',listParam{ii},'), x=1; else, x=0; end']);
if x
continue;
end
disp(['The parameter ', listParam{ii}, ' is not a NaN.']);
end
Strangely, x happens to appear in the script's stack. However, this is far from a good piece of code. Never use this method.
Edit: about the "control" scope of eval.
I'm not talking about the variable scope / workspace of eval. Hints can be found in several documentations like this and this. In short, eval uses the "current" workspace.
However, I found the following things interesting:
Running continue directly in eval
for ii = 1:2
eval('continue')
ii+10
end
This simply fails, as shown in the question. The error is Error: A CONTINUE may only be used within a FOR or WHILE loop. which means the continue inside eval cannot find any loop (the for loop).
Calling a separate script in a for loop
for ii = 1:2
foo
ii+10
end
while script foo.m is
ii
continue
First of all, in foo.m Mlint gives a red-line warning, which usually indicates an error that can stop the code from running, saying that CONTINUE is only valid in a FOR or WHILE loop. But pressing F5 on foo.m does not have any problem - in fact running a single continue anywhere does not crash the code.
Running the main script gives output
ii =
1
ii =
2
>>
....so foo.m catches the for loop?
eval('foo') - I really don't understand Matlab
for ii = 1:2
eval('foo')
ii+10
end
The result surprised me a bit.
ii =
1
ans =
11
ii =
2
ans =
12
>>
Thought: eval runs the code in an independent control flow, but shares its workspace with the current one. It is (something but not exactly) like an isolated world model, in which (here in Matlab) different pieces of code can interact with the same set of variables, but cannot interact with each other in the sense of control flow.
Unfortunately, I was unable to find any existing resources as reference to prove this idea.
This does not change my solution: in any case, try to avoid using eval.

Using strmatch in a loop

Can I do the something below coded using or without loop?
Actually I am having a character array comprising of unique words more than 5000 and other array comprising of approx 3000 words. I want to search each word in my array named as word in other array named as uniques and wish to create a feature vector i.e. values 1 if exists and 0 if doesn't.
I am doing the following..
load 'uniques' %uniques={'alpha','ok',abc'};
fid=fopen(myfilename);
words=textscan(fid,'%s');
fclose(fid);
word=words{1,1}; %word={'good','bad',anywhere','countries','ok',done','abc'}
for i=1:size(uniques,2)
ind=strmatch(word(i), uniques, 'exact');
end
Now, seeing above as examples before uniques and word arays, my system must return 0 for good as good is not there in uniques and same 0 values but 1 for ok because it does exist in uniques. All in all, I must have in the end, {0,0,0,0,1,0,1} ..
After I run, it gives me ind=[]
Please guide
You have described the exact functionality of the ismember function:
ismember(word, uniques);
as an aside, this is what #nkjt was saying about fixing your loop:
for i=1:size(word,2)
ind(i)=strmatch(word(i), uniques, 'exact');
end
But this loop is unnecessary since Matlab has this as a built in function

open statement in a recursive subroutine

I wanted to write my results into a file which is produced in a recursive subroutine. And I also wanted to assign the data(read) in the file to an array in my main program in fortran90.
program permutations
implicit none
call generate (position_min)
open(unit=20, file="a.dat", status="old")
do i=1,720
read(20,*)(G(i,j),j=1,6)
end do
contains
recursive subroutine generate (position)
implicit none
integer, intent (in) :: position
integer :: value
if (position > position_max) then
open(unit=20, file="a.dat", status="unknown")
write (20, *) permutation
else
call generate(position+1)
end if
end subroutine generate
end program permutations
This program gives me the following runtime error.
At line 19 of file p2.f90 (unit = 20, file = 'a.dat')
Fortran runtime error: End of file
How do I fix this?
I think the answer is primarily my comment to the question. If you look at your code (neglecting the undeclared variable issue), in particular the if-statement of the recursive subroutine, you should note that you have
if (position > position_max) then
open(unit=20, file="a.dat", status="unknown")
write (20, *) permutation
else
call generate(position+1)
end if
that is, you are only writing to file if position > position_max. Satisfying this condition writes one line to a.dat and then completes all of the previous if statements. What you probably meant to have was it writing to file each time through the recursive loop; to do that, you would want something like
open(20,file="a.dat",status="unknown")
write(20,*) permutation
close(20)
if(position > position_max) then
return
else
call generate(position+1)
endif
In running this, I found I was getting 2 extra lines (due to writing at position=position_min and at position=position_max). You probably could tweak that to get exactly 720, but I think that this part is irrelevant because you can change your read loop to the following
i=1
do
read(20,*,iostat=ierr) G(i,:)
if(ierr/=0) exit
i = i+1
enddo
A normal read returns an iostat of 0 and an end-of-file returns -1, so as long as you can read you will continue the loop and break when the EOF is found.
After fixing up the undeclared variables, adding the close(20) statement, and adjusting as I commented above, I had no problems writing and reading in the recursive subroutine.