2015-07-06 11 views
5

Tôi muốn tìm và không đỉnh trong một vectơ có chiều rộng ngắn nhất, tức là các đỉnh có một mẫu đơn không khác và các mẫu lân cận bằng không, tức là [0 ~0 0]~0 là đỉnh cao. Ví dụ: nếu x = [1 0 2 0 0 3 0 4 5 6 0 7 0 8], thì tôi muốn tìm 2, 3 và 7 và đặt chúng là 0, tức là x trở thành [1 0 0 0 0 0 0 4 5 6 0 0 0 8]. Đoạn mã sau thực hiện thủ thuật, nhưng có cách nào hiệu quả hơn hay tốt hơn để thực hiện điều này, hay một hàm Matlab tồn tại mà tìm thấy một mẫu nhất định trong một vectơ (hay thậm chí là ma trận)?Phương pháp hiệu quả để tìm một giá trị được bao quanh bởi các số 0 trong một vector

% remove peaks of shape [0 ~0 0] 
k = find(x); 
for j=k' 
    if j==numel(x) || j==1 
    elseif ~x(j-1) && ~x(j+1) 
     x(j) = 0; 
    end 
end 
+0

'X' có thể chứa cả số dương và số âm? – Dan

+0

Để có đầy đủ, bạn cũng có thể thêm đầu ra dự kiến ​​có liên quan đến đầu vào ví dụ của bạn. Nếu không thì [mcve] rất tốt (http://stackoverflow.com/help/mcve) – kkuilla

Trả lời

8

Bạn đang tìm kiếm các phần tử trong đó chập với hạt nhân [1,1,1] không khác với bản gốc. Các biến chứng duy nhất là chúng ta phải bỏ qua các trường hợp cạnh:

x = [1 0 2 0 0 3 0 4 5 6 0 7 0 8]; 
y = conv(x,[1,1,1],'same'); 
ind = find(x==y); 
x(ind(2:end-1)) = 0 

hoặc

x(find(x(2:end-1)==conv(x,[1,1,1],'valid'))+1) = 0 

nếu phải đối mặt với viễn cảnh của cả hai con số tích cực và tiêu cực, sau đó dựa trên gợi ý Craigim của trong các ý kiến:

xx = abs(x); 
x(find(xx(2:end-1)==conv(xx,[1,1,1],'valid'))+1) = 0 
+1

Thực ra - điều này sẽ bị hỏng nếu bạn cho phép số âm, tức là nếu 'x = [1 0 2 0 0 3 0 4 5 -4 0 7 0 8] 'thì phương pháp này cũng loại bỏ' 5'. Đó có phải là vấn đề cho trường hợp sử dụng của bạn không? – Dan

+4

Thay vì xoay vòng với vectơ gốc, hãy liên kết với 'xx = x ~ = 0 '. – craigim

+0

Tôi thích câu trả lời này tốt nhất, bởi vì tôi muốn làm điều này với một sự chập chững, nhưng tôi đã xoay chuyển với [0 1 0], mà thực tế không làm gì cả. Việc kết hợp với một mảng các 'n' có' n' không đồng đều sẽ phát hiện một đỉnh mẫu đơn được bao quanh bởi các số 0 (n-1)/2'. Cảm ơn! – Erik

5

Sử dụng conv (dọc theo dòng câu trả lời của Dan) có lẽ là cách tiếp cận tốt nhất; nhưng nó cũng có thể được thực hiện với strfind:

x(strfind(x~=0, [0 1 0]) + 1) = 0; 

Hoặc sử dụng diff để tính toán sự khác biệt thứ hai theo thứ tự:

x(find(diff(~x, 2)==2) + 1) = 0; 
+0

Phiên bản 'str' không hoạt động đối với tôi. 'error: strfind: PATTERN phải là một chuỗi hoặc mảng ô của chuỗi' – kkuilla

+0

@kkuilla Nó hoạt động trong Matlab R2015a. Nhưng nó không làm tôi ngạc nhiên rằng nó không hoạt động trong tất cả các phiên bản, bởi vì sử dụng 'strfind' với các con số là không có giấy tờ. Phiên bản nào bạn đang sử dụng? –

+0

Hiện tại, GNU Octave Phiên bản 3.8.1 :-( – kkuilla

5

Dưới đây sẽ là cách của tôi để làm điều đó

x_add = x(1:end-2) + x(2:end-1) + x(3:end); 
x(find([0,x(2:end-1)==x_add,0]))=0; 

Nó thêm giá trị trước đó và giá trị tiếp theo cho từng giá trị và kiểm tra giá trị nào không thay đổi

+0

Tôi thích điều này, cảm ơn! khó đọc hơn một chút và do đó khó hiểu hơn các giải pháp khác, nhưng nhỏ gọn và khá thông minh. – Erik

Các vấn đề liên quan