2017-01-31 2 views
2

У меня есть вектор вроде этого:Как повторять каждый третий элемент вектора?

h = [1,2,3,4,5,6,7,8,9,10,11,12] 

И я хочу повторить каждый третий элемент, как так:

h_rep = [1,2,3,3,4,5,6,6,7,8,9,9,10,11,12,12] 

Как сделать это элегантно в MATLAB? Фактические массивы огромны, поэтому в идеале я не хочу писать цикл for. Есть ли векторизованный способ сделать это?

+1

ли кто-нибудь из наших ответов помочь? – rayryeng

+0

Сроки для решений здесь были бы интересны ... – gnovice

+1

@gnovice Я собираюсь рассказать все решения сегодня вечером и отредактировать свой пост. Спасибо за идею! Кстати, я думаю, что решение Луиса будет самым быстрым ... он использует только индексирование. – rayryeng

ответ

6

Один из способов сделать это - использовать последнюю функцию repelem, которая была выпущена в версии R2015b, где вы можете повторять каждый элемент в векторе определенное количество раз. В этом случае указать вектор, где каждый третий элемент представляет собой 2 с остальной частью значений будучи 1, как количество раз, чтобы повторить соответствующий элемент, а затем использовать функцию:

N = numel(h); 
rep = ones(1, N); 
rep(3:3:end) = 2; 
h_rep = repelem(h, rep); 

Использования примера: h = 1 : 12, мы, таким образом, получаем:

>> h_rep 

h_rep = 

    1  2  3  3  4  5  6  6  7  8  9  9 10 11 12 12 

Если repelem не доступен для вас, то умное использование cumsum может помочь. В принципе, обратите внимание, что для каждых трех элементов следующий - это копия предыдущего элемента. Если бы у нас был индикаторный индикатор [1 1 1 0], где 1 - это позиция, которую мы хотим скопировать, и 0 сообщает нам скопировать последнее значение с использованием суммарной суммы или cumsum на повторные версии этого вектора - точно 1 + (numel(h)/4) даст нам именно то, что нам нужно для индексации до h. Таким образом, создать вектор из единиц, что является длиной h с добавлением 1 + (numel(h)/4, чтобы гарантировать, что мы делаем пространство для повторяющихся элементов, то убедитесь, что каждый четвертый элемент устанавливается в 0 перед нанесением cumsum:

N = numel(h); 
rep = ones(1, N + 1 + (N/4)); 
rep(4:4:end) = 0; 
rep = cumsum(rep); 
h_rep = h(rep); 

Таким образом, :

>> h_rep 

h_rep = 

    1  2  3  3  4  5  6  6  7  8  9  9 10 11 12 12 

последнее предложение (спасибо пользователя @bremen_matt) будет reshape ваш вектор в матрицу, так что он имеет 3 строки, дублирует последнюю строку, а затем изменить полученную дублированную матрицу обратно в один вектор:

h_rep = reshape(h, 3, []); 
h_rep = reshape([h_rep; h_rep(end,:)], 1, []); 

Мы снова получаем:

>> h_rep 

h_rep = 

    1  2  3  3  4  5  6  6  7  8  9  9 10 11 12 12 

Конечно очевидный нюанс с указанным кодом является то, что длина вектора h равномерно делится на 4.

1

Я думаю, что это сделайте это:

h = [1,2,3,4,5,6,7,8,9,10,11,12]; 
h0=kron(h,[1 1]) 
h_rep=h0(mod(1:length(h0),2)==0 | mod(1:length(h0),3)==2) 

Ответ:

1  2  3  3  4  5  6  6  7  8  9  9 10 11 12 12 

Объяснение: После дублирования каждого элемента, вы выбираете только те, которые вы хотите. Вы можете расширить эту идею, чтобы дублировать вторую и третью. и т.д..

+2

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

6

(Модифицированные в соответствии с правильными наблюдениями rayryeng в) ...

Другим решением является поиграться с функцией перекроить. Если изменить матрицу к матрице 3XN первого ...

B = reshape(h,3,[]) 

, а затем скопируйте последнюю строку

B = [B;B(end,:)] 

И, наконец, векторизации решение ...

B(:).' 
+0

Пара комментариев: (1) Вы можете указать '[]' вместо 'numel (h)/3' в последнем аргументе' reshape', чтобы автоматически вычислить количество столбцов, в которых вы нуждаетесь. (2) OP может хотеть вектор строки, поэтому транспонируйте 'B (:)' после того, как вы закончите. – rayryeng

4

Вы можете использование только индексации:

h = [1,2,3,4,5,6,7,8,9,10,11,12]; % initial data 
n = 3; % step for repetition 
h_rep = h(ceil(n/(n+1):n/(n+1):end)); 
3

Подход на основе индексов (с использованием sort):

h_rep = h(sort([1:numel(h) 3:3:numel(h)])); 

Или немного короче синтаксис ...

h_rep = h(sort([1:end 3:3:end])); 
+0

Интересный подход с 'sort'! – rayryeng

Смежные вопросы