Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
Help with a Tricky For Loop

Subject: Help with a Tricky For Loop

From: ade77

Date: 8 Oct, 2009 16:32:04

Message: 1 of 11

I have an array like this a = [2 4; 3 5; 6 7; 6 9].

1. The program compares consecutive rows of the first column, (starting from the first row and second row), checks if the difference is equal to 1 or 0.

2. if (1) is true, then it removes the row with smaller second column.
3. If (1) is not true, it goes to the second row , and third row, and compare the two.

In my example above, it compares 2,3(consecutive rows , first column), since the difference is 1, it removes first row[2 4] because 4 is less than 5( in the second column).

Hence, I now have a new array, [3 5; 6 7;6 9], and I would like it to repeat the same: compare first row, second row both of first column. In my example, 3,6 difference is 3, so it will leave the rows, then next comapre row 2, and row 3 (6,6), since the difference is 0, it will delete row [6 7]. because 7 is less than 9 in second column

So my final array will be [3 5; 6 9]


Thanks for any help

Subject: Help with a Tricky For Loop

From: dpb

Date: 8 Oct, 2009 17:33:59

Message: 2 of 11

ade77 wrote:
> I have an array like this a = [2 4; 3 5; 6 7; 6 9].
>
> 1. The program compares consecutive rows of the first column,
> (starting from the first row and second row), checks if the difference
> is equal to 1 or 0.
>
> 2. if (1) is true, then it removes the row with smaller second column.
> 3. If (1) is not true, it goes to the second row , and third row, and compare the two.
>
> In my example above, it compares 2,3(consecutive rows , first
> column), since the difference is 1, it removes first row[2 4] because
> 4 is less than 5( in the second column).
>
> Hence, I now have a new array, [3 5; 6 7;6 9], and I would like it to
> repeat the same: compare first row, second row both of first column. In
> my example, 3,6 difference is 3, so it will leave the rows, then next
> comapre row 2, and row 3 (6,6), since the difference is 0, it will
> delete row [6 7]. because 7 is less than 9 in second column
>
> So my final array will be [3 5; 6 9]


Try this...

 >> a = [2 4; 3 5; 6 7; 6 9];
 >> d = [zeros(1,size(a,2)); diff(a,1)];
 >> b= a(r(:,1)<2 & r(:,2)>0,:)
b =
      3 5
      6 9
 >>

--

Subject: Help with a Tricky For Loop

From: dpb

Date: 8 Oct, 2009 18:03:20

Message: 3 of 11

dpb wrote:
> ade77 wrote:
>> I have an array like this a = [2 4; 3 5; 6 7; 6 9].
>>
>> 1. The program compares consecutive rows of the first column,
>> (starting from the first row and second row), checks if the difference
>> is equal to 1 or 0.
>>
>> 2. if (1) is true, then it removes the row with smaller second column.
>> 3. If (1) is not true, it goes to the second row , and third row, and
>> compare the two.
>>
>> In my example above, it compares 2,3(consecutive rows , first column),
>> since the difference is 1, it removes first row[2 4] because
>> 4 is less than 5( in the second column).
>>
>> Hence, I now have a new array, [3 5; 6 7;6 9], and I would like it to
>> repeat the same: compare first row, second row both of first column. In
>> my example, 3,6 difference is 3, so it will leave the rows, then next
>> comapre row 2, and row 3 (6,6), since the difference is 0, it will
>> delete row [6 7]. because 7 is less than 9 in second column
>>
>> So my final array will be [3 5; 6 9]
>
>
> Try this...
>
> >> a = [2 4; 3 5; 6 7; 6 9];
> >> d = [zeros(1,size(a,2)); diff(a,1)];
> >> b= a(r(:,1)<2 & r(:,2)>0,:)
> b =
> 3 5
> 6 9
> >>
>

Typo, sorry -- changed from testing w/ "r" for the difference matrix
(for "rows") to "d" and then didn't fixup...

  b= a(d(:,1)<2 & d(:,2)>0,:)

--

Subject: Help with a Tricky For Loop

From: dpb

Date: 8 Oct, 2009 18:31:00

Message: 4 of 11

dpb wrote:
...
> b= a(d(:,1)<2 & d(:,2)>0,:)

OBTW, if a(:,1) is not strictly ascending then the first test above will
need to include >0 to not select every row for which the difference is
negative as well as same or one greater.

--

Subject: Help with a Tricky For Loop

From: Matt Fig

Date: 8 Oct, 2009 23:29:18

Message: 5 of 11

dpb <none@non.net> wrote in message <hal82q$pq$1@news.eternal-september.org>...
> Try this...
>
> >> a = [2 4; 3 5; 6 7; 6 9];
> >> d = [zeros(1,size(a,2)); diff(a,1)];
> >> b= a(r(:,1)<2 & r(:,2)>0,:)
> b =
> 3 5
> 6 9
> >>
>


Hmm, I took this completely differently. But since the OP hasn't replied, maybe you're correct.

Subject: Help with a Tricky For Loop

From: dpb

Date: 8 Oct, 2009 23:48:17

Message: 6 of 11

Matt Fig wrote:
> dpb <none@non.net> wrote in message <hal82q$pq$1@news.eternal-september.org>...
>> Try this...
>>
>> >> a = [2 4; 3 5; 6 7; 6 9];
>> >> d = [zeros(1,size(a,2)); diff(a,1)];
>> >> b= a(r(:,1)<2 & r(:,2)>0,:)
>> b =
>> 3 5
>> 6 9
>> >>
>>
>
>
> Hmm, I took this completely differently. But since the OP hasn't
> replied, maybe you're correct.

I don't know; it's what I thought OP was asking for...

I don't know whether is general-enough for the end purpose as don't know
what the desired result would be for several cases including if there's
a series of rows >2 that fulfill the condition...

I think it is kinda' cute, though... :)

--

Subject: Help with a Tricky For Loop

From: ade77

Date: 10 Oct, 2009 04:25:02

Message: 7 of 11

Thanks guys, sorry for the late reply, the method you propose looks cute, but only works for the example I have given, I am looking for a more general code.

In reality, I am going to have a long array(n rows, 2 cols), and of course the good thing is that the first column is always in ascending order.

For example, if I change my original array to [2 4; 3 5; 3 4; 6 9;9 4; 10 1 ], I expect to get [3 5;6 9 ; 9 4].

steps:
1. from column 1, check row 1and row2, diff is 1,then compare (row 1,row 2) of second column, 4 is less than 5, throw away row 1

2. repeat step 1, but now your new array is now [3 5; 3 4; 6 9; 9 4; 10 1]. from the first column, subtract the first two rows, the diff is 0, compare second col, delete second row.

3. Your new array is now [3 5; 6 9; 9 4; 10 1]. Repeat step 1, difference of first column, first two rows is 3, hence do nothing.
4.Then compare the next consecutive row, that is row 2 and row 3 (first column), the diff is 3, do nothing.
5. Next compare row 3,and row 4, diff is 1, now check which is larger in column 2, 4 is larger throw away row [10 1].

dpb <none@non.net> wrote in message <halu0f$p2i$1@news.eternal-september.org>...
> Matt Fig wrote:
> > dpb <none@non.net> wrote in message <hal82q$pq$1@news.eternal-september.org>...
> >> Try this...
> >>
> >> >> a = [2 4; 3 5; 6 7; 6 9];
> >> >> d = [zeros(1,size(a,2)); diff(a,1)];
> >> >> b= a(r(:,1)<2 & r(:,2)>0,:)
> >> b =
> >> 3 5
> >> 6 9
> >> >>
> >>
> >
> >
> > Hmm, I took this completely differently. But since the OP hasn't
> > replied, maybe you're correct.
>
> I don't know; it's what I thought OP was asking for...
>
> I don't know whether is general-enough for the end purpose as don't know
> what the desired result would be for several cases including if there's
> a series of rows >2 that fulfill the condition...
>
> I think it is kinda' cute, though... :)
>
> --

Subject: Help with a Tricky For Loop

From: Matt Fig

Date: 10 Oct, 2009 05:28:01

Message: 8 of 11

I wrote this up real quick, so it may not be the best solution. This is how I understood the problem, with only one or two things still unclear.



% Data
a = [2 4; 3 5; 3 4; 6 9;9 4; 10 1 ];



% Engine
tfi = 1; % True/False flag for inner loop.
tfo = 1; % True/False flag for outer loop.
L = size(a,1); % The starting number of rows.
S = L; % Keep track of deletions.

while tfo
    crnt = 1; % Start at beginning of array.
    nxt = 2;
    while tfi
        CMP = a(crnt,1) - a(nxt,1);
        
        if CMP==1 || CMP==0 || CMP==-1
            if a(crnt,2) < a(nxt,2)
                a(crnt,:) = [];
            else
                a(nxt,:) = []; % Will delete in case of equality!!
            end
            
            S = S - 1;
            break % Every time array is changed, start over (?).
        else
            crnt = crnt + 1; % Step forward
            nxt = nxt + 1;
            
            if nxt > L % At the end of the array.
                break
            end
        end
    end

    if L==S || S==1 % The array didn't change or has only 1 row.
        break % The only way out of the outer loop.
    else
        tfo = true; % Go through again, the array has changed.
        tfi = true;
        L = S;
    end
end

Subject: Help with a Tricky For Loop

From: dpb

Date: 10 Oct, 2009 13:10:21

Message: 9 of 11

ade77 wrote:
> Thanks guys, sorry for the late reply, the method you propose looks
> cute, but only works for the example I have given, I am looking for a
> more general code.
...

I misread the 2nd condition; Matt was right--I thought it was the 2nd
condition was the 2nd column row was to be larger than the first, not
simply the larger of the two. Otherwise, the "trick" would work if
applied recursively I think.

W/ the actual reqm't, the loop is only way out I think.

--

Subject: Help with a Tricky For Loop

From: ade77

Date: 10 Oct, 2009 16:08:01

Message: 10 of 11


dpb and Matt, thank you very much for your time.

Yes the last code Matt wrote seems to do the trick. I will check my complete array, if there is one or two problem I will let you guys know.

I appreciate your input.

dpb <none@non.net> wrote in message <haq1cg$819$1@news.eternal-september.org>...
> ade77 wrote:
> > Thanks guys, sorry for the late reply, the method you propose looks
> > cute, but only works for the example I have given, I am looking for a
> > more general code.
> ...
>
> I misread the 2nd condition; Matt was right--I thought it was the 2nd
> condition was the 2nd column row was to be larger than the first, not
> simply the larger of the two. Otherwise, the "trick" would work if
> applied recursively I think.
>
> W/ the actual reqm't, the loop is only way out I think.
>
> --

Subject: Help with a Tricky For Loop

From: Matt Fig

Date: 10 Oct, 2009 16:10:02

Message: 11 of 11

Ade77,

I missed in your second post that the first row was sorted. This of course simplifies things considerably. For this less-general case, and with a little cleaning-up, I would rewrite the loop solution I gave earlier as the following. Note that my remaining uncertainties are marked with a (?).



L = size(a,1); % The starting number of rows.
S = L; % Keep track of deletions.

while 1
    crnt = 1; % Start at beginning of array every time (?) in outer loop.
    while 1
        CMP = a(crnt + 1,1) - a(crnt,1);
        if CMP==1 || CMP==0
            if a(crnt,2) < a((crnt + 1),2)
                a(crnt,:) = [];
            else
                a(crnt + 1,:) = []; % Will delete in case of equality(?) in col 2.
            end
            S = S - 1;
            break % When array is changed, start over (?). Only way out of inner loop.
        else
            crnt = crnt + 1; % Step forward
            if (crnt + 1) > L % At the end of the array.
                break
            end
        end
    end
    if L==S || S==1 % The array didn't change or has only 1 row.
        break % The only way out of the outer loop.
    else
        L = S;
    end
end



One thing which could dramatically increase the speed, if you are worried about that, would be to figure out how to build an index vector instead of re-writing the array every time the comparison condition is met, then index into a at the end. I'll leave that up to you!

Tags for this Thread

No tags are associated with this thread.

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us