2013-06-19 18 views
5

Mam macierz 6X4 M1 zawierającą tylko zera. Mam również dwie tablice 1D Y1 i Y2 każda o długości 4. Te dwie tablice zawierają żądane wartości indeksu. Teraz chcę, aby ustawić (konwersja do 1) elementy macierzy M1 takie, że M1(Y1:Y2) jest równa 1Indeksowanie macierzy 2D w programie Matlab

dla Ex: Y1=[1 2 2 1] i Y2=[3 4 5 3]
następnie, M1 powinny być

1 0 0 1 
1 1 1 1 
1 1 1 1 
0 1 1 0 
0 0 1 0 
0 0 0 0 

mogę zrób to za pomocą pętli for. Ale czy istnieje zoptymalizowany sposób na zrobienie tego? (Zamierzam użyć znacznie większych matryc)

Odpowiedz

6

Nie może być oth er techniki, ale używa to operacji elementów, które są szalenie równoległe.

Bardzo proste rozwiązanie. Dzięki @Shai

>> [rows, cols] = size(M); 
>> Y1=[1 2 2 1]; Y2=[3 4 5 3]; 
>> M = bsxfun(@ge, (1:rows)', Y1) & bsxfun(@le, (1:rows)', Y2) 
M = 
    1  0  0  1 
    1  1  1  1 
    1  1  1  1 
    0  1  1  0 
    0  0  1  0 
    0  0  0  0 

niepotrzebnie skomplikowane kodu

[rows, cols] = size(M); 
offsets = ((1 : cols) - 1) * rows 
Y1 = offsets + Y1; 
Y2 = offsets + Y2; 

M = reshape(1:numel(M), rows, cols); 
M = bsxfun(@ge, M, Y1) & bsxfun(@le, M, Y2); 
+0

wielki użycie 'bsxfun' - ale można to zrobić bez użycia' offsets' – Shai

+0

@shai Nadal istnieje bug, jestem ustalające to. –

+0

odpowiedź na moje pytanie można znaleźć po najechaniu myszką na dno mojej odpowiedzi ;-) – Shai

8

użyć cumsum!

>> szM = size(M1); 
>> M1(sub2ind(szM, Y1, 1:szM(2))) = 1 
M1 = 
1  0  0  1 
0  1  1  0 
0  0  0  0 
0  0  0  0 
0  0  0  0 
0  0  0  0 
>> M1(sub2ind(szM, Y2+1, 1:szM(2))) = -1 
M1 = 
1  0  0  1 
0  1  1  0 
0  0  0  0 
-1  0  0 -1 
0 -1  0  0 
0  0 -1  0 
>> M = cumsum(M,1) 
M = 
1  0  0  1 
1  1  1  1 
1  1  1  1 
0  1  1  0 
0  0  1  0 
0  0  0  0 

Pułapka: Jeżeli którykolwiek z Y2 równa 6 niż ustawienie Y2+1 -1 przekracza wymiar osnowy.
Aby rozwiązać ten problem można dodać dwie linie przed ustawieniem na -1 elementów M:

>> cols = 1:szM(2); 
>> sel = Y2 < szM(1); 
>> M1(sub2ind(szM, Y2(sel)+1, cols(sel))) = -1 

spin-off dla Pavan Yalamanchili's answer użyciu bsxfun: (Umieszczenie do zobaczenia :)

użyciu bsxfun bez offsets:
M1 = bsxfun(@ge, (1:size(M1,1))', Y1) & bsxfun(@le, (1:size(M1,1))', Y2);

Powiązane problemy