2017-11-30 13 views
7

सबसे कम तरीका है कि मैं यह जांचने के लिए सोच सकता हूं कि सरणी arr में सभी तत्व बराबर हैं all(arr[1] .== arr)। हालांकि यह निश्चित रूप से छोटा है, यह थोड़ा सा सुरुचिपूर्ण लगता है। क्या कोई अंतर्निहित कार्य है जो यह करता है?जांचें कि जूलिया सरणी के सभी तत्व बराबर हैं

मुझे संदेह है कि ==(arr...) की लाइनों के साथ कुछ है, लेकिन यह काम नहीं करता है क्योंकि == ऑपरेटर केवल दो तर्क ले सकता है। मुझे यकीन नहीं है कि जूलिया arr[1] == arr[2] == arr[3] जैसे अभिव्यक्तियों का विश्लेषण कैसे करता है, लेकिन क्या इसे किसी सरणी में तत्वों की मनमानी संख्या के साथ अनुकूलित करने का कोई तरीका है?

उत्तर

7

महान प्रश्न @tparker और महान उत्तर @ कोलिंटबावर। दोनों के बारे में सोचने की कोशिश करते समय, यह सीधे-आगे पुराने स्कूल जूलियन तरीके-के -for -loop को आजमाने के लिए हुआ। नतीजा समान तत्वों के लंबे वेक्टर के महत्वपूर्ण इनपुट पर तेजी से था, इसलिए मैं यह नोट जोड़ रहा हूं। साथ ही, फ़ंक्शन का नाम allequal उल्लेख करने के लिए पर्याप्त उचित प्रतीत होता है।

allequal_1(x) = all(y->y==x[1],x) 

allequal_2(x) = foldl(==,x) # another way but doesn't short-circuit :(

@inline function allequal_3(x) 
    length(x) < 2 && return true 
    e1 = x[1] 
    i = 2 
    @inbounds for i=2:length(x) 
     x[i] == e1 || return false 
    end 
    return true 
end 

और बेंचमार्क: तो यहाँ वेरिएंट हैं

julia> using BenchmarkTools 

julia> v = fill(1,10_000_000); # long vector of 1s 

julia> allequal_1(v) 
true 

julia> allequal_2(v) 
true 

julia> allequal_3(v) 
true 

julia> @btime allequal_1($v); 
    9.573 ms (1 allocation: 16 bytes) 

julia> @btime allequal_2($v); 
    10.585 ms (0 allocations: 0 bytes) 

julia> @btime allequal_3($v); 
    6.853 ms (0 allocations: 0 bytes) 

अद्यतन: है जब वहाँ एक शॉर्ट सर्किट अवसर बेंचमार्क के एक अन्य महत्वपूर्ण मामला है। तो (के रूप में commment में अनुरोध):

julia> v[100] = 2 
2 

julia> allequal_1(v),allequal_2(v),allequal_3(v) 
(false, false, false) 

julia> @btime allequal_1($v); 
    108.946 ns (1 allocation: 16 bytes) 

julia> @btime allequal_2($v); 
    10.325 ms (0 allocations: 0 bytes) 

julia> @btime allequal_3($v); 
    68.221 ns (0 allocations: 0 bytes) 

दूसरे संस्करण allequal_2 किरायों बुरी तरह के रूप में यह नहीं शॉर्ट सर्किट है।

सभी चीजें बराबर होती हैं, for संस्करण बेस में allequal होना चाहिए।

+0

धन्यवाद, 'फ़ोल्ड' वास्तव में वह फ़ंक्शन है जिसे मैं ढूंढ रहा था।क्या आपको लगता है कि तीसरा कार्यान्वयन तेज क्यों है, '@ इनबाउंड्स' से परे कारण है? – tparker

+0

मुझे वास्तव में पसंद है कि जूलिया बेस का निर्माण सामान्य कार्यों के शीर्ष पर संयोजन और निर्माण करके किया जाता है, जिससे कई कार्यान्वयन उच्च-स्तर और अमूर्त होते हैं। उदाहरण के लिए 'reduce.jl' देखें। मैं पसंद करता हूं कि एक 'allequal' (हालांकि यह वास्तव में आधार में नहीं होना चाहिए) ऐसा कुछ होगा, जो कि कुछ हाइपर-अनुकूलित कस्टम लूप बनाने के बजाय' सभी 'जैसे कुछ सामान्य निर्माण के शीर्ष पर बनाया गया है। इस तरह, 'all' के प्रदर्शन में सुधार करने से प्रत्येक फ़ंक्शन में सुधार होगा जो उस पर निर्भर करता है। – DNF

+0

बीटीडब्ल्यू। 'foldl' _not_ शॉर्ट-सर्किट में दिखाई देता है, इसलिए यह निश्चित रूप से इष्टतम नहीं है। – DNF

9

all सही समाधान है, लेकिन आप विधेय p और iterable itr के लिए विधि all(p, itr) चाहते हैं, क्योंकि यह शॉर्ट-सर्किट व्यवहार (के रूप में जल्द ही एक false के रूप में पाया जाता है को तोड़ने) को रोजगार देगा। तो: के रूप में यह समय है समय संकलन

for n = 100000:250000:1100000 
    x = rand(1:2, n); 
    @time all(x .== x[1]); 
    @time all(y->y==x[1], x); 
    println("------------------------") 
end 

पहले यात्रा पर ध्यान न दें:

all(y->y==x[1], x) 

अंतर देखने के लिए, आप निम्नलिखित थोड़ा गति परीक्षण चला सकते हैं।

0.000177 seconds (22 allocations: 17.266 KiB) 
    0.006155 seconds (976 allocations: 55.062 KiB) 
------------------------ 
    0.000531 seconds (23 allocations: 47.719 KiB) 
    0.000003 seconds (1 allocation: 16 bytes) 
------------------------ 
    0.000872 seconds (23 allocations: 78.219 KiB) 
    0.000001 seconds (1 allocation: 16 bytes) 
------------------------ 
    0.001210 seconds (23 allocations: 108.781 KiB) 
    0.000001 seconds (1 allocation: 16 bytes) 
------------------------ 
    0.001538 seconds (23 allocations: 139.281 KiB) 
    0.000002 seconds (1 allocation: 16 bytes) 

पहला समाधान काफी स्पष्ट रूप से हे (एन), जबकि दूसरे हे है (1) सबसे अच्छा और हे (एन) सबसे खराब में (itr के लिए डेटा पैदा करने की प्रक्रिया के आधार पर) पर।

+0

वाह, महान जवाब! हालांकि मुझे आश्चर्य है कि पहले तत्व से मैन्युअल रूप से तुलना करने से कहीं अधिक कॉम्पैक्ट वाक्यविन्यास नहीं है। – tparker

+2

@tparker 'allsame (x) = all (y-> y == x [1], x)'। भाषा के बारे में अच्छी चीजों में से एक यह है कि इन शॉर्टकट्स को स्वयं लिखना कितना आसान है और उन्हें अपने मूल पैकेज में बैठना है। आम तौर पर, जूलिया समुदाय में यथासंभव ट्रिम के रूप में 'बेस' रखने के लिए एक मजबूत धक्का है। हर प्रकार के ऑपरेशन के लिए अच्छा, सरल, फ़ंक्शन नाम पैकेज में हो सकते हैं, और यदि पर्याप्त लोग इसे पसंद करते हैं, तो पैकेज लोकप्रिय हो जाता है, और इसी तरह ... लेकिन 'बेस' दुबला और तेज़ रहता है। –

+0

सुंदर है कि यह खाली सरणी के लिए भी काम करता है: 'allsame ([]) == true', जैसा होना चाहिए, क्योंकि रिक्त सरणी के अंदर कोई अलग तत्व नहीं हैं। – mschauer

संबंधित मुद्दे