2010-04-14 31 views

Trả lời

79

Nếu bạn chỉ muốn loại bỏ các số không, rời khỏi phi số không đằng sau trong một, sau đó là giải pháp tốt nhất là

a(a==0) = []; 

này sẽ xoá zero yếu tố, sử dụng một cách tiếp cận lập chỉ mục logic trong MATLAB. Khi chỉ mục đến một vec-tơ là một vectơ boolean có cùng độ dài với vectơ, thì MATLAB có thể sử dụng kết quả boolean đó để lập chỉ mục nó. Vì vậy, điều này tương đương với

a(find(a==0)) = []; 

Và khi bạn đặt một số thành phần mảng thành [] trong MATLAB, quy ước là xóa chúng.

Nếu bạn muốn đặt số không vào một kết quả mới b, trong khi để lại một không thay đổi, cách tốt nhất có lẽ là

b = a(a ~= 0); 

Một lần nữa, lập chỉ mục logic được sử dụng ở đây. Bạn có thể sử dụng phiên bản tương đương (về kết quả) của

b = a(find(a ~= 0)); 

nhưng mlint sẽ kết thúc suy giảm dòng là một nơi chỉ số hoàn toàn logic là hiệu quả hơn, và do đó thích hợp hơn.

Như mọi khi, hãy cẩn thận kiểm tra CHÍNH XÁC về số không hoặc cho bất kỳ số nào, nếu bạn đã chấp nhận các phần tử nằm trong một số dung sai epsilon bằng không. Những thử nghiệm như thế này

b = a(abs(a) >= tol); 

Chỉ giữ lại những thành phần này ít nhất là dung sai của bạn.

+1

hoặc ví dụ đầu tiên, 'a = a (a ~ = 0)' là đủ, việc gán tại chỗ hoạt động tốt. Điểm tốt về thử nghiệm đối với một số nhỏ thay vì 0. – mtrw

+0

@ woodchips: Chỉ cần đăng một so sánh hiệu suất bên dưới :) – tim

3
b = a(find(a~=0)) 
+2

chỉ 'b = a (tìm (a))' là đủ, mặc định là tìm các giá trị khác. – wich

+5

hoặc 'b = a (a ~ = 0)' là đủ, lập chỉ mục logic được ngụ ý. – mtrw

+1

Ý kiến ​​hay, tôi cảm thấy tồi tệ khi nhận được câu trả lời nghèo nàn của tôi upvoted. –

8

Tôi chỉ tình cờ gặp vấn đề này và muốn tìm một cái gì đó về hiệu suất, nhưng tôi không thể, vì vậy tôi đã viết một kịch bản chuẩn trên của riêng tôi:

% Config: 
rows = 1e6; 
runs = 50; 

% Start: 
orig = round(rand(rows, 1)); 

t1 = 0; 
for i = 1:runs 
    A = orig; 
    tic 
    A(A == 0) = []; 
    t1 = t1 + toc; 
end 
t1 = t1/runs; 

t2 = 0; 
for i = 1:runs 
    A = orig; 
    tic 
    A = A(A ~= 0); 
    t2 = t2 + toc; 
end 
t2 = t2/runs; 

t1 
t2 
t1/t2 

Vì vậy, bạn thấy, các giải pháp sử dụng A = A(A ~= 0) là nhanh hơn của hai :)

4

Tôi thường kết thúc làm những việc như thế này. Do đó tôi đã cố gắng viết một hàm đơn giản để 'tách' các phần tử không mong muốn một cách dễ dàng. Đây biến matlab luận một chút lộn ngược, nhưng có vẻ tốt:

b = snip(a,'0') 

bạn có thể tìm thấy các tập tin chức năng tại địa chỉ: http://www.mathworks.co.uk/matlabcentral/fileexchange/41941-snip-m-snip-elements-out-of-vectorsmatrices

Nó cũng làm việc với tất cả các khác 'x', nan hoặc bất cứ yếu tố.

+6

Đó là một chiếc búa hùng mạnh để đánh cắp một con ruồi nhỏ xíu ... – Shai

2

Tại sao không chỉ, a=a(~~a) hoặc a(~a)=[]. Nó tương đương với các cách tiếp cận khác nhưng chắc chắn ít nét chính hơn.

2

liệu

a=[0 3 0 0 7 10 3 0 1 0 7 7 1 7 4] 

Do

aa=nonzeros(a)' 

quả

aa=[3 7 10 3 1 7 7 1 7 4] 
+0

Tại sao không làm cho bài đăng này tốt hơn: thêm liên kết đến tài liệu và sử dụng đánh dấu thích hợp cho mã của bạn – Sjon

+0

Tôi nghĩ đây là một câu trả lời tuyệt vời! Nó sẽ là tốt đẹp để có được một so sánh với các đề xuất khác. –

2

Bạn có thể sử dụng thưa thớt (a), mà sẽ trở

(1,2) 1

(1,4) 3

Điều này cho phép bạn giữ thông tin về nơi các mục nhập khác không được sử dụng.

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