Репликация элемента разумного массива в соответствии с подсчетом [дубликат

StackOverflow https://stackoverflow.com/questions/2382319

Вопрос

Мой вопрос похож на это один, но я хотел бы воспроизвести каждый элемент в соответствии с количеством, указанным во втором массиве одного и того же размера.

Пример этого, скажем, у меня был массив v = [3 1 9 4], Я хочу использовать rep = [2 3 1 5] реплицировать первый элемент 2 раза, второй три раза, и так далее, чтобы получить [3 3 1 1 1 9 4 4 4 4 4].

Пока я использую простую цикл, чтобы выполнить работу. Это то, что я начал с:

vv = [];
for i=1:numel(v)
    vv = [vv repmat(v(i),1,rep(i))];
end

Мне удалось улучшить путем предоплатывающего пространства:

vv = zeros(1,sum(rep));
c = cumsum([1 rep]);
for i=1:numel(v)
    vv(c(i):c(i)+rep(i)-1) = repmat(v(i),1,rep(i));
end

Однако я все еще чувствую, что должен быть более умным способом сделать это ... спасибо

Это было полезно?

Решение

Вот так, как мне нравится достичь этого:

>> index = zeros(1,sum(rep));
>> index(cumsum([1 rep(1:end-1)])) = 1;

index =

     1     0     1     0     0     1     1     0     0     0     0

>> index = cumsum(index)

index =

     1     1     2     2     2     3     4     4     4     4     4

>> vv = v(index)

vv =

     3     3     1     1     1     9     4     4     4     4     4

Это работает, сначала создавая индекс вектора нулей одинаковой длины, что и конечный счет всех значений. Выполняя совокупную сумму rep Vector с удаленным последним элементом и A 1, помещенный в начале, я получаю вектор индексов в index Показано, где начнется группы реплицированных значений. Эти точки отмечены теми. Когда совокупная сумма выполняется на index, Я получаю окончательный вектор индекса, который я могу использовать для указания в v Создать вектор гетерогенно реплицированных значений.

Другие советы

Чтобы добавить в список возможных решений, рассмотрите этот:

vv = cellfun(@(a,b)repmat(a,1,b), num2cell(v), num2cell(rep), 'UniformOutput',0);
vv = [vv{:}];

Это намного медленнее, чем один Гновице..

То, что вы пытаетесь сделать, это Диодиа. Отказ Высокий уровень надежный / векторизированная утилита является Представление FEX rude():

% example inputs
counts = [2, 3, 1];
values = [24,3,30];

результат

rude(counts, values)
ans =
    24    24     3     3     3    30

Обратите внимание, что эта функция также выполняет противоположную работу, то есть Кодировки длины пробега Вектор или другие слова возвращаются values и соответствующее counts.

accumarray Функция может быть использована для выполнения работы кода, если Zeros выйдите из rep множество

function vv = repeatElements(v, rep)
index = accumarray(cumsum(rep)'+1, 1);
vv = v(cumsum(index(1:end-1))+1);
end

Это работает, похожие на решение GNOVICE, за исключением того, что индексы накапливаются вместо того, чтобы быть назначенным к 1. Это позволяет пропустить некоторые индексы (3 и 6 в приведенном ниже примере) и удалить соответствующие элементы из выхода.

>> v = [3 1 42 9 4 42];
>> rep = [2 3 0 1 5 0];
>> index = accumarray(cumsum(rep)'+1, 1)'

index =

     0     0     1     0     0     2     1     0     0     0     0     2

>> cumsum(index(1:end-1))+1

ans =

     1     1     2     2     2     4     5     5     5     5     5

>> vv = v(cumsum(index(1:end-1))+1)

vv =

     3     3     1     1     1     9     4     4     4     4     4
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top