Domanda

Questa domanda ha già una risposta qui:

La mia domanda è simile a questa uno, ma vorrei replicare ogni elemento in base a un conteggio specificato in un secondo array della stessa dimensione.

Un esempio di questo, dire che avevo un array v = [3 1 9 4], Voglio usare rep = [2 3 1 5] per replicare il primo elemento 2 volte, il secondo tre volte e così via per ottenere [3 3 1 1 1 9 4 4 4 4 4].

Finora sto usando un semplice ciclo per fare il lavoro. Questo è ciò con cui ho iniziato:

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

Sono riuscito a migliorare preallocando lo spazio:

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

Comunque sento ancora che ci deve essere un modo più intelligente per farlo ... grazie

È stato utile?

Soluzione

Ecco un modo in cui mi piace realizzare questo:

>> 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

Questo funziona prima creando un vettore indice di zero della stessa lunghezza del conteggio finale di tutti i valori. Eseguendo una somma cumulativa del rep Vector con l'ultimo elemento rimosso e un 1 posizionato all'inizio, ottengo un vettore di indici in index mostrando dove inizieranno i gruppi di valori replicati. Questi punti sono contrassegnati da quelli. Quando viene eseguita una somma cumulativa index, Ottengo un vettore indice finale che posso usare per indicizzare v Per creare il vettore di valori eterogenei.

Altri suggerimenti

Per aggiungere all'elenco di possibili soluzioni, considera questo:

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

Questo è molto più lento di quello di Gnovice..

Quello che stai cercando di fare è decodifica della lunghezza. Un'utilità di alto livello affidabile/vettoriale è la Presentazione FEX rude():

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

il risultato

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

Si noti che questa funzione esegue anche l'operazione opposta, cioè codifica di lunghezza un vettore o in altre parole ritorna values e il corrispondente counts.

accumarray La funzione può essere utilizzata per far funzionare il codice se gli zeri escono rep Vettore

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

Questo funziona simile alla soluzione di Gnovice, tranne per il fatto che gli indici vengono accumulati invece assegnati a 1. Ciò consente di saltare alcuni indici (3 e 6 nell'esempio seguente) e rimuovere gli elementi corrispondenti dall'output.

>> 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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top