2016-04-09 28 views
8

Sono abbastanza nuovo in Julia e non so come rimuovere i duplicati consecutivi in ​​un array. Per esempio, se si prende questa matrice:Rimuovi duplicati consecutivi in ​​Julia

`v=[8,8,8,9,5,5,8,8,1];` 

vorrei ottenere il v1 vettore tale che:

v1 = [8,9,5,8,1];

Qualcuno mi potrebbe aiutare? Grazie molto.

+0

Sì, hai ragione, dovrebbe includere 1. Ci scusiamo! –

+1

@SamyJelassi puoi modificare la tua domanda per includere '1'. – niczky12

risposta

8

Un metodo potrebbe essere quello di definire:

function fastuniq(v) 
    v1 = Vector{eltype(v)}() 
    if length(v)>0 
    laste = v[1] 
    push!(v1,laste) 
    for e in v 
     if e != laste 
     laste = e 
     push!(v1,laste) 
     end 
    end 
    end 
    return v1 
end 

E con questa funzione, si ha:

julia> println(fastuniq(v)) 
[8,9,5,8,1] 

Ma, quando si tratta di array, una necessità di decidere se gli elementi sono di essere profondo o poco profondo copiato. In caso di numeri interi, non importa.

+0

È il modo più grasso per farlo? –

+1

Abbastanza veloce. Forse alcune direttive di ottimizzazione come '@ inbounds' su' for' potrebbero aiutare. La funzione 'push!' È ottimizzata in modo che molti piccoli 'push!' Es non esercitino troppo frequentemente l'allocazione di memoria. –

+1

Se la percentuale di elementi rimossi è generalmente piccola, si potrebbe desiderare di avere anche un sizehint! per ottimizzare l'allocazione della matrice di output. Un'altra cosa per velocizzarla (se è frequente il caso in cui non si trovano duplicati) è quella di avere una funzione che scansiona rapidamente per il primo duplicato, e se non vengono trovati duplicati, è sufficiente restituire l'array originale, o usare 'copia '(a seconda che sia necessaria o meno una copia) –

4

Questo è molto più lento di quanto la funzione di @ DanGetz ma qui è un modo per farlo in una sola riga:

function notsofastunique(v) 
    return [v[1]; v[2:end][v[2:end] .!= v[1:end-1]]] 
end 


>println(notsofastunique(v)) 
[8,9,5,8,1] 

Forse è utile per chi cerca una soluzione vecotrised.

+0

stessa idea, ma forse più chiara:' lag (a, n = 1) = append!(compilare (NaN, n), a [1: (end-n)]); v [v.! = lag (v)] ' –

4

Nell'obiettivo della soluzione one-liner @ niczky12, il seguente utilizza il pacchetto Iterators.jl (molto utile e lentamente migrante in Base).

using Iterators   # install with Pkg.add("Iterators") 

neatuniq(v) = map(first,filter(p->p[1]!=p[2],partition(chain(v,[nothing]),2,1))) 

non hanno fatto alcun benchmark, ma dovrebbe essere ok (ma più lento della for funzionano più based).

6

In StatsBase.jl c'è una funzione rle (codifica Run-length) che fa esattamente questo.

+2

Soluzione piacevole. Ha anche scoperto un potenziale bug in 'rle': un vettore vuoto produce un'eccezione (nessun controllo prima di accedere al primo elemento). –

+0

Il commento precedente ha portato a PR https://github.com/JuliaStats/StatsBase.jl/pull/154. Essenzialmente, l'invariante 'inverse_rle (rle (v) ...) == v' dovrebbe funzionare anche quando' v' è un vettore vuoto. –

2

Solo per il gusto di praticare ...

Ecco un altro po 'la funzione è possibile utilizzare per fare questo, questa funzione è operativa per i valori non negativi (inluding 0) solo.

function anotherone(v) 
    v1 = zeros(eltype(v),length(v)) 
    v1[1]=v[1]+1 
    for e = 2:length(v) 
     if v[e] != v[e-1] 
      v1[e] = v[e]+1  
     end 
    end 
    return v1[find(v1)]-1 
end 

edit:

L'aggiunta di una versione più, secondo l'input nei commenti. Penso che questo dovrebbe essere ancora più veloce, forse potresti testarlo :) Questa versione dovrebbe funzionare anche per i numeri negativi.

function anotherone(v) 
    v1 = falses(length(v)) 
    v1[1]=true 
    for e = 2:length(v) 
     if v[e] != v[e-1] 
      v1[e] = true  
     end 
    end 
    return v[v1] 
end 
+1

Un po 'più semplice sarebbe utilizzare direttamente l'indicizzazione logica. Rendi 'v1' una matrice logica (' v1 = falses (length (v)) '), e poi imposta a true nei luoghi in cui ti stai assegnando gli elementi. Ora puoi semplicemente 'return v [v1]', e funzionerà per tutti i valori e tipi di elementi. –