Как я могу эффективно удалить нули из (не разреженной) матрицы?

У меня есть матрица:

x = [0 0 0 1 1 0 5 0 7 0];

Мне нужно удалить все нули, например:

x = [1 1 5 7];

Матрицы, которые я использую, являются большими (1x15000), и мне нужно сделать это несколько раз (5000+), поэтому эффективность является ключевой!

Ответ 1

Один из способов:

x(x == 0) = [];

Заметка о сроках:

Как упоминалось woodchips, этот метод кажется медленным по сравнению с тем, который используется KitsuneYMG. Это также было отмечено Лорен в одном из своих сообщений в блогах MathWorks. Поскольку вы упомянули о необходимости делать это тысячи раз, вы можете заметить разницу, и в этом случае я сначала попробую x = x(x~=0);.

ПРЕДУПРЕЖДЕНИЕ: Остерегайтесь, если вы используете нецелые числа. Если, например, у вас есть очень небольшое число, которое вы хотели бы рассмотреть достаточно близко к нулю, чтобы он был удален, вышеуказанный код не удалит его. Удаляются только точные нули. Следующее поможет вам также удалить числа "достаточно близко" до нуля:

tolerance = 0.0001;  % Choose a threshold for "close enough to zero"
x(abs(x) <= tolerance) = [];

Ответ 2

Просто чтобы быть другим:

x=x(x~=0);

или

x=x(abs(x)>threshold);

У этого есть бонус работы над сложными числами.

Ответ 3

Это три общих решения. Это помогает увидеть разницу.

x = round(rand(1,15000));

y = x;

tic,y(y==0) = [];toc

Elapsed time is 0.004398 seconds.

y = x;

tic,y = y(y~=0);toc

Elapsed time is 0.001759 seconds.

y = x;

tic,y = y(find(y));toc

Elapsed time is 0.003579 seconds.

Как вы видите, самым дешевым способом является прямой логический индекс, выбирая элементы, которые нужно сохранить. Находка дороже, поскольку Matlab находит эти элементы, возвращая их список, а затем индексирует в вектор.

Ответ 4

Здесь другой путь

y = x (find (x))

Я оставлю это вам, чтобы выяснить относительную эффективность различных подходов, которые вы пытаетесь - пишите и дайте нам знать.

Ответ 5

Несмотря на то, что мои результаты по времени не являются окончательными, будь то значительно быстрее, это, по-видимому, самый быстрый и простой подход:

y = nonzeros(y) 

Ответ 6

x = [0 0 0 1 1 0 5 0 7 0]
y = [0 2 0 1 1 2 5 2 7 0]

Тогда x2 и y2 можно получить как:

x2=x(~(x==0 & y==0))
y2=y(~(x==0 & y==0))

x2 = [0     1     1     0     5     0     7]
y2 = [2     1     1     2     5     2     7]

Надеюсь, это поможет!