2016-04-09 17 views
8

में लगातार डुप्लिकेट निकालें मैं जूलिया में काफी नया हूं और मुझे नहीं पता कि सरणी में लगातार डुप्लीकेट को कैसे हटाया जाए। उदाहरण के लिए आप इस सरणी ले:जूलिया

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

मैं वेक्टर v1 प्राप्त करने के लिए चाहते हैं कि इस तरह के:

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

किसी को भी मेरी मदद कर सकते हैं? बहुत धन्यवाद।

+0

हाँ आप सही हैं इसमें शामिल होना चाहिए 1. क्षमा करें! –

+1

@ सैमी जेलास्सी आप '1'' शामिल करने के लिए अपना प्रश्न संपादित कर सकते हैं। – niczky12

उत्तर

8

एक विधि को परिभाषित करने से हो सकता है:

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 

और इस समारोह के साथ, आपके पास:

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

लेकिन, जब सरणियों के साथ काम कर, अगर तत्वों गहरे हो रहे हैं तय करने के लिए एक की जरूरत या उथले नकल। पूर्णांक के मामले में, इससे कोई फर्क नहीं पड़ता।

+0

क्या यह करने का सबसे तेज़ तरीका है? –

+1

बहुत तेज़। शायद कुछ अनुकूलन निर्देश जैसे '@ inbounds'' के लिए 'मदद' कर सकते हैं। 'पुश!' फ़ंक्शन को अनुकूलित किया गया है ताकि बहुत से छोटे 'पुश!' एस स्मृति आवंटन का प्रयोग न करें। –

+1

तत्वों का प्रतिशत हटाया आम तौर पर छोटा है, तो आप भी एक sizehint करना चाहते हो सकता है! आउटपुट सरणी के आवंटन को अनुकूलित करने के लिए। एक और बात यह गति (अगर यह अक्सर मामले में जहां कोई डुप्लिकेट पाए जाते हैं) एक समारोह है कि जल्दी से पहले डुप्लिकेट के लिए स्कैन करने के लिए होगा, और यदि कोई डुप्लिकेट पाए जाते हैं, बस मूल सरणी लौटने, या 'प्रति का उपयोग '(इस पर निर्भर करता है कि आपको प्रतिलिपि की आवश्यकता है या नहीं) –

4

यह @ DanGetz के समारोह की तुलना में बहुत धीमी है, लेकिन यहाँ एक पंक्ति में यह करने के लिए एक तरीका है:

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] 

शायद यह किसी एक vecotrised समाधान की तलाश के लिए उपयोगी है।

+0

एक ही विचार है, लेकिन शायद स्पष्ट:' अंतराल (ए, एन = 1) = संलग्न करें!(भरें (NaN, n), एक [1: (अंत-एन)]); वी [वी।! = अंतराल (वी)] ' –

4

भावना @ niczky12 एक-लाइनर समाधान लक्ष्य में, निम्नलिखित Iterators.jl पैकेज (बहुत उपयोगी और धीरे-धीरे बेस में माइग्रेटिंग) का उपयोग करता है।

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

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

किसी भी मानक नहीं किया है, लेकिन यह (अब for आधारित समारोह से लेकिन धीमी) ठीक होना चाहिए।

6

StatsBase.jl में वहाँ एक rle समारोह (रन-लंबाई एन्कोडिंग) वास्तव में यह करता है।

बस अभ्यास की खातिर
+2

अच्छा समाधान। इसने 'राले' में एक संभावित बग भी खुलासा किया: एक खाली वेक्टर एक अपवाद उत्पन्न करता है (पहले तत्व तक पहुंचने से पहले कोई जांच नहीं)। –

+0

पिछली टिप्पणी पीआर https://github.com/JuliaStats/StatsBase.jl/pull/154 के लिए नेतृत्व किया। अनिवार्य रूप से, invariant 'inverse_rle (rle (v) ...) == v' अभी भी काम करना चाहिए जब' v' एक खाली वेक्टर है। –

2

...

यहाँ, इस समारोह गैर नकारात्मक मूल्यों (inluding 0) के लिए ही काम करेंगे एक और छोटे से समारोह यदि आप ऐसा करने का उपयोग कर सकते है।

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 

संपादित करें:

टिप्पणी में इनपुट के अनुसार एक और संस्करण जोड़ा जा रहा है,। मुझे लगता है कि यह भी तेज होना चाहिए, शायद आप इसका परीक्षण कर सकते हैं :) इस संस्करण को नकारात्मक संख्याओं के लिए भी काम करना चाहिए।

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

लॉजिकल इंडेक्सिंग का उपयोग करने के लिए सीधे थोड़ा आसान होगा। 'V1' को लॉजिकल सरणी बनाएं (' v1 = falses (length (v)) '), और फिर उन स्थानों पर सत्य पर सेट करें जहां आप इसे तत्व निर्दिष्ट कर रहे थे। अब आप बस 'v v [v1] 'वापस कर सकते हैं, और यह सभी मानों और तत्व प्रकारों के लिए काम करेगा। –