Octave / Matlab: добавление новых элементов в вектор

Имея вектор x, я должен добавить элемент (newElem).

Есть ли разница между -

x(end+1) = newElem; 

и

x = [x newElem];

?


person URL87    schedule 24.04.2013    source источник


Ответы (3)


x(end+1) = newElem немного надежнее.

x = [x newElem] будет работать, только если x является вектором-строкой, если это вектор-столбец, x = [x; newElem] должен использоваться. x(end+1) = newElem, однако, работает как с векторами-строками, так и с векторами-столбцами.

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

person ThijsW    schedule 24.04.2013
comment
Также для второго метода сначала необходимо инициализировать x! - person Dan; 24.04.2013
comment
@RodyOldenhuis, без проблем! Я сделал то же самое, наверное, в то же время. @Dan, это правда, но, поскольку в упомянутом вопросе есть вектор x (размера n), я вроде предположил, что n ненулевой, а вектор уже инициализирован :) - person ThijsW; 24.04.2013
comment
@ThijsW: Тем не менее, использование end, а не какой-то переменной n (которая может быть global, насколько вы знаете!) Является более универсальным, надежным и бесплатным способом. - person Rody Oldenhuis; 24.04.2013
comment
@Dan x должен быть инициализирован для обоих методов. - person Robino; 17.09.2017
comment
@Robino Я так не думаю, у меня нет MATLAB для проверки, но в октаве вы определенно можете сделать x(end+1)=... без инициализации x, и я почти уверен, что вы также можете сделать это в MATLAB - person Dan; 17.09.2017
comment
@Dan x(end+1)=123 дает Неопределенную функцию или переменную 'x'. - person Robino; 18.09.2017

Чтобы добавить к ответу @ 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.

person Dan    schedule 24.04.2013
comment
+1, отредактировано, чтобы добавить и очевидное. Я протестирую еще раз на реальном процессоре (сейчас я использую этот дрянной, ненадежный, нехороший APU ...) - person Rody Oldenhuis; 24.04.2013
comment
@Dan, у меня тоже самое, я получаю 0,028 за третий вариант и 8,909 за последний - person ThijsW; 24.04.2013
comment
Я также думаю, что JIT-оптимизация для случая x(end+1) - довольно недавнее дополнение (R2012a или около того ...). Я смутно помню, как читал что-то подобное в некоторых чейндженотах в Smoe Point. Я также получаю очень разные результаты на моем APU / Matlab R2010, но я не уверен, связано ли это с версией Matlab или APU ... - person Rody Oldenhuis; 24.04.2013
comment
@RodyOldenhuis и ThiijsW см. Мое недавнее сравнение между старым и новым Matlab - person Dan; 24.04.2013
comment
@Dan: Ах :) ОК, ТЕПЕРЬ все лучше :) - person Rody Oldenhuis; 24.04.2013

Как упоминалось ранее, использование x(end+1) = newElem имеет то преимущество, что оно позволяет объединить ваш вектор со скаляром, независимо от того, транспонирован ваш вектор или нет. Поэтому он более надежен для добавления скаляров.

Однако не следует забывать, что x = [x newElem] также будет работать, когда вы попытаетесь добавить несколько элементов одновременно. Более того, это более естественно обобщается на случай, когда вы хотите объединить матрицы. M = [M M1 M2 M3]


В общем, если вам нужно решение, которое позволяет объединить ваш существующий вектор x с newElem, который может быть или не быть скаляром, это должно помочь:

 x(end+(1:numel(newElem)))=newElem
person Dennis Jaheruddin    schedule 24.04.2013
comment
Я думаю, ваш последний пример должен быть: x (end + 1: end + length (newElem)) = newElem - person Digna; 22.01.2014
comment
@Digna Спасибо за обнаружение ошибки, я обновил ответ, чтобы исправить проблему. - person Dennis Jaheruddin; 22.01.2014
comment
С моим Matlab2011b было также резкое (~ 50x) улучшение скорости конкатенации векторов этим методом по сравнению с методом a = [a b]. - person JaBe; 08.04.2015
comment
@Jabe метод [a b] - это конкатенация. Я полагаю, вы говорите, что расширение массива быстрее конкатенации? - person Robino; 17.09.2017