find second minimum in a row in matlab without sorting

find second minimum in a row in matlab without sorting.
excluding zero
example A = [ 3.5 2 1.6 1.456 0 1.9 2.6 ; 3.8 2.6 3.9 0 6 1.564 0 ]

3 Comments

Sounds like homework. What have you tried?
It's just an example
I have tried (min2) = [A,[1:pos-1 pos+1:end]
Pos is position of first minimum

Sign in to comment.

 Accepted Answer

[mini1(i1,1),mini1(i1,2)] = min(abs(L(i1,([1:mini(i1,2)-1 mini(i1,2)+1:end]))));

4 Comments

Note that Nitin Sapre's entire solution is below.
This isn't a complete solution and it's certainly not a good approach.
  • No one knows what L, m, i1, or mini is. Why would more than 1 variable be necessary?
  • a loop is certainly unnecessary
  • applying the abs() results in minimum magnitudes which was never mentioned in the question.
  • Most importantly, there are two much better approaches proposed here, both of which can be adapted to apply abs().
Nitin Sapre's entire (incomplete) solution
for i1 = 1:m %treg(1:ti,i1)
% for col = find(L(m,:) ~= 0)
L(L== 0) = NaN;
[mini(i1,1),mini(i1,2)] = min(abs(L(i1,:))); %first minimum
% fprintf("loop ends here")
[mini1(i1,1),mini1(i1,2)] = min(i1,abs(L([1:mini(i1,2)-1 mini(i1,2)+1:end])));
%its this
[mini1(i1,1),mini1(i1,2)] = min(abs(L(i1,([1:mini(i1,2)-1 mini(i1,2)+1:end]))));
Ekaterina Sadovaya's approach is to toss the first min and then find the 2nd min (adapted below)
A = [ 3.5 2 1.6 1.456 0 1.9 2.6 ; 3.8 2.6 3.9 0 6 1.564 0 ];
A(A==0) = NaN;
[~, minIdx] = min(abs(A),[],2)
A(sub2ind(size(A),(1:size(A,1))',minIdx)) = NaN;
min(abs(A),[],2) %<--- there's your answer
Guillaume's approach is to use mink which was also recommended in the comment section of Ekaterina Sadovaya's solution (adapted below).
A = [ 3.5 2 1.6 1.456 0 1.9 2.6 ; 3.8 2.6 3.9 0 6 1.564 0 ];
A(A==0) = NaN;
minvals = mink(abs(A), 2, 2)
minvals(:, 2) %<--- there's your answer
To add to Adam's list
  • min is always called with two outputs, but only one is ever needed in each call (2nd output, the first two times, 1st output the 3rd time)
  • Most likely (I haven't tested), due to the constant splitting and stitching of the rows, requiring many copy operations, the code is probably much slower than sorting the whole matrix and taking the 2nd column.
  • There's a major bug in the code. The 2nd min call is completely wrong.
To other people looking for similar solutions, don't use this answer!
yes sir ur approach is very much faster but Sir thing is L is my main matrix of size mxn i1 is variable to update rows and mini is matrix to store postion and value.
since i need to store value of 2nd min tin the positon of 1st min in a row and replace all other values with first min i used this approach.
since am beginner in matlab i dont know much about this.
Any kind of help ffrom your side will be appreciate.
thank you sir
"Any kind of help ffrom your side will be appreciate"
If you have any questions about the other answers that were recommended here, please let us know. I've addapted both answers to your needs in my comment above.
Sorting may be an even better approach and it's still not clear why sorting is off the table.
An accepted answer is a sign to inexperienced users that an answer is the best solution which clearly isn't the case here. This is why you are being urged to reconsider the other options.

Sign in to comment.

More Answers (2)

You can exclude the first minimum. So, for example for the first row it will be
A1 = A(1,:);
[first_min_value, index] = min(A1);
A1(index) = [];
second_min_value = min(A1);

7 Comments

...or a variation of (hint)
max(mink(A,2))
I have also tried this already it is considering a 0 as 1st minimum.
and its considering second element of the row
Prior to searching for the 2nd min, you could replace all 0s with NaN or Inf. I still think this is homework since there's no explanation as to why sorting is not allowed so I'll only make that suggestion and you can figure out the rest.
hint: use ==
for i1 = 1:m %treg(1:ti,i1)
% for col = find(L(m,:) ~= 0)
L(L== 0) = NaN;
[mini(i1,1),mini(i1,2)] = min(abs(L(i1,:))); %first minimum
% fprintf("loop ends here")
[mini1(i1,1),mini1(i1,2)] = min(i1,abs(L([1:mini(i1,2)-1 mini(i1,2)+1:end])));
this is what i have done
and this is not an homework
No need for a loop.
Here's a similar example.
x = randi(20,8,8) %Random integers between 1 and 20
% Replace all values greater than the mean.
x(x > mean(x(:))) = NaN;
i got the ans in my soln only.
thanks for ur help and this is not my homework
for i1 = 1:m %treg(1:ti,i1)
% for col = find(L(m,:) ~= 0)
L(L== 0) = NaN;
[mini(i1,1),mini(i1,2)] = min(abs(L(i1,:))); %first minimum
% fprintf("loop ends here")
[mini1(i1,1),mini1(i1,2)] = min(i1,abs(L([1:mini(i1,2)-1 mini(i1,2)+1:end])));
its this
[mini1(i1,1),mini1(i1,2)] = min(abs(L(i1,([1:mini(i1,2)-1 mini(i1,2)+1:end]))));

Sign in to comment.

Use mink
A = [ 3.5 2 1.6 1.456 0 1.9 2.6 ; 3.8 2.6 3.9 0 6 1.564 0 ];
minvals = mink(A, 2, 2); %first 2 miminums along dimension 2.
minvals(:, 2) %get the 2nd one

Categories

Products

Release

R2018a

Asked:

on 16 Oct 2019

Edited:

on 21 Oct 2019

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!