У меня есть вектор, например
a = [0 1 0 3]
Я хочу превратить a в b, который равен b = [1 3]
.
Как это сделать вообще? Итак, у меня есть вектор с некоторыми нулевыми компонентами, и я хочу удалить нули и оставить только ненулевые числа?
У меня есть вектор, например
a = [0 1 0 3]
Я хочу превратить a в b, который равен b = [1 3]
.
Как это сделать вообще? Итак, у меня есть вектор с некоторыми нулевыми компонентами, и я хочу удалить нули и оставить только ненулевые числа?
Если вы просто хотите удалить нули, оставив ненулевые нули в a, тогда самое лучшее решение -
a(a==0) = [];
Это удаляет нулевые элементы, используя подход логической индексации в MATLAB. Когда индекс к вектору является булевым вектором той же длины, что и вектор, то MATLAB может использовать этот логический результат для его индексации. Таким образом, это эквивалентно
a(find(a==0)) = [];
И когда вы устанавливаете некоторые элементы массива в [] в MATLAB, соглашение должно их удалить.
Если вы хотите поместить нули в новый результат b, оставив неизменным, лучший способ, вероятно,
b = a(a ~= 0);
Опять же, здесь используется логическое индексирование. Вы могли бы использовать эквивалентную версию (в терминах результата)
b = a(find(a ~= 0));
но mlint в конечном итоге помещает строку как ту, где чисто логический индекс был более эффективным и, следовательно, более уместным.
Как всегда, будьте осторожны с ТОЧНЫМИ испытаниями для нуля или для любого числа, если бы вы приняли элементы a, которые были в пределах некоторого эпсилонского толерантности к нулю. Проводят ли эти тесты как
b = a(abs(a) >= tol);
Это сохраняет только те элементы из a, которые по крайней мере такие же, как ваш допуск.
Я только что наткнулся на эту проблему и хотел найти что-то о производительности, но не смог, поэтому сам написал тест script:
% 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
Итак, вы видите, что решение с использованием A = A(A ~= 0)
является более быстрым из двух:)
Я часто делал такие вещи. Поэтому я попытался написать простую функцию, которая легко "освобождает" нежелательные элементы. Это немного изменяет логику Matlab, но выглядит хорошо:
b = snip(a,'0')
вы можете найти файл функции по адресу: http://www.mathworks.co.uk/matlabcentral/fileexchange/41941-snip-m-snip-elements-out-of-vectorsmatrices
Он также работает со всеми другими элементами "x", наном или другими.
b = a(find(a~=0))
Почему не просто, a=a(~~a)
или a(~a)=[]
. Это эквивалентно другим подходам, но, конечно, менее ключевым штрихам.
Данные
a=[0 3 0 0 7 10 3 0 1 0 7 7 1 7 4]
Do
aa=nonzeros(a)'
Результат
aa=[3 7 10 3 1 7 7 1 7 4]
Вы можете использовать разреженный (a), который возвратит
(1,2) 1
(1,4) 3
Это позволяет вам сохранять информацию о том, где были использованы ненулевые записи.