Октава / Matlab: Додавання нових елементів до вектора


75

Маючи вектор, xі я повинен додати елемент ( newElem).

Чи є якась різниця між -

x(end+1) = newElem; 

і

x = [x newElem];

?

Відповіді:


93

x(end+1) = newElem трохи надійніший.

x = [x newElem] буде працювати лише в тому випадку, якщо x є рядковим вектором, якщо це стовпець, x = [x; newElem]слід використовувати вектор . x(end+1) = newElemоднак працює як для векторів рядків, так і для стовпців.

Однак загалом слід уникати вирощування векторів. Якщо ви багато робите це, це може звести ваш код до сканування. Подумайте: вирощування масиву передбачає виділення нового простору, копіювання всього, додавання нового елемента та очищення старого безладу ... Зовсім марна трата часу, якщо ви заздалегідь знали правильний розмір :)


3
Також для другого методу xпотрібно спочатку ініціалізувати!
Ден,

1
@RodyOldenhuis, не біда! Я робив те саме, мабуть, одночасно. @Dan, це правда, але, оскільки в запитанні згадувалося "наявність вектора x(розміру n)", я начебто припустив, nщо він ненульовий і вектор вже ініціалізується :)
ThijsW

1
@ThijsW: Тим не менш, використання endзамість якоїсь змінної n(що може бути globalдля всіх, кого ти знаєш!) Є більш універсальним, надійним і безкоштовним способом
Роді Олденхайс,

@Dan x повинен бути ініціалізований для обох методів.
Робіно

@Robino Я не думаю, у мене немає MATLAB для перевірки, але в октаві ви, звичайно, можете обійтися x(end+1)=...без xініціалізації, і я майже впевнений, що ви можете це зробити і в MATLAB
Дан,

28

Просто щоб додати відповідь @ ThijsW, є значна перевага швидкості для першого методу перед методом конкатенації:

big = 1e5;
tic;
x = rand(big,1);
toc

x = zeros(big,1);
tic;
for ii = 1:big
    x(ii) = rand;
end
toc

x = []; 
tic; 
for ii = 1:big
    x(end+1) = rand; 
end; 
toc 

x = []; 
tic; 
for ii = 1:big
    x = [x rand]; 
end; 
toc

   Elapsed time is 0.004611 seconds.
   Elapsed time is 0.016448 seconds.
   Elapsed time is 0.034107 seconds.
   Elapsed time is 12.341434 seconds.

Я отримав ці часи в 2012b, однак, коли я запускав той самий код на тому самому комп'ютері в matlab 2010a, який я отримую

Elapsed time is 0.003044 seconds.
Elapsed time is 0.009947 seconds.
Elapsed time is 12.013875 seconds.
Elapsed time is 12.165593 seconds.

Тож я думаю, перевага у швидкості стосується лише новіших версій Matlab


+1, відредаговано, щоб додати також очевидне. Я ще раз протестую на "справжньому" процесорі (я зараз на цій паскудній ненадійній
недоброякісній штуці

@Dan, те саме для мене, я отримую 0,028 за третій варіант і 8,909 за останній
ThijsW

1
Я також думаю, що оптимізація JIT для цього x(end+1)випадку є досить недавнім доповненням (R2012a або близько того ...). Я vagualey пам’ятаю, читав щось подібне у деяких ченгенотах у точці смої. Я також отримую дуже різні результати на моєму APU / Matlab R2010, але я не впевнений, чи це пов’язано з версією Matlab чи APU ...
Роді Олденхайс,

@RodyOldenhuis та ThiijsW бачать моє недавнє порівняння між старими та новішими matlab
Dan

@Dan: Ах :) Добре, ТЕПЕР це все краще :)
Роді Олденхайс

4

Як вже згадувалося раніше, використання x(end+1) = newElem переваги має ту перевагу, що дозволяє зв’язати вектор зі скаляром, незалежно від того, транспонований чи ні. Тому він є більш надійним для додавання скалярів.

Однак не слід забувати, що x = [x newElem]це також буде працювати, коли ви намагаєтесь додати кілька елементів одночасно. Крім того, це узагальнює дещо природніше для випадку, коли ви хочете об'єднати матриці.M = [M M1 M2 M3]


Загалом, якщо вам потрібне рішення, яке дозволяє об’єднати ваш існуючий вектор xіз newElemскаляром, який може бути, а може не бути, це має зробити трюк:

 x(end+(1:numel(newElem)))=newElem

1
Я думаю, що вашим останнім прикладом має бути: x (end + 1: end + length (newElem)) = newElem
Digna

@Digna Дякую, що знайшли помилку, я оновив відповідь, щоб вирішити проблему.
Денніс Джахеруддін

1
З моїм Matlab2011b також було різке (~ 50x) покращення швидкості при векторній конкатенації за допомогою цього методу порівняно з методом a = [ab].
JaBe

@Jabe методом [ab] є конкатенація. Припускаю, ви говорите, що розширення масиву відбувається швидше, ніж конкатенація?
Robino
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.