Репликация элемента разумного массива в соответствии с подсчетом [дубликат
-
24-09-2019 - |
Вопрос
Этот вопрос уже имеет ответ здесь:
Мой вопрос похож на это один, но я хотел бы воспроизвести каждый элемент в соответствии с количеством, указанным во втором массиве одного и того же размера.
Пример этого, скажем, у меня был массив 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