2015-04-12 15 views
7

में समान मूल्य है स्विफ्ट में कोई फ़ंक्शन है जो जांचता है कि सरणी के सभी तत्वों का एक ही मूल्य है या नहीं? मेरे मामले में, यह Int प्रकार की एक सरणी है। मुझे पता है कि मैं लूप के लिए एक सरल का उपयोग कर इसे फिर से चला सकता हूं, मैं बस सोच रहा था कि क्या ऐसा कुछ है जो बनाया गया है और तेज़ है।जांचें कि क्या सरणी के सभी तत्वों में स्विफ्ट

उत्तर

21

कोई भी तरीका सभी तत्वों से अधिक पुनरावृति चाहिए जब तक एक अलग तत्व पाया जाता है:

func allEqualUsingLoop<T : Equatable>(array : [T]) -> Bool { 
    if let firstElem = array.first { 
     for elem in array { 
      if elem != firstElem { 
       return false 
      } 
     } 
    } 
    return true 
} 
एक स्पष्ट पाश के बजाय

आप फ़ंक्शन का उपयोग कर सकते हैं:

func allEqualUsingContains<T : Equatable>(array : [T]) -> Bool { 
    if let firstElem = array.first { 
     return !contains(array, { $0 != firstElem }) 
    } 
    return true 
} 

सरणी तत्वों Hashable हैं (जैसे Int) तो आप सरणी तत्वों से Set (स्विफ्ट 1.2 के बाद से उपलब्ध) बना सकते हैं और जांच सकते हैं कि इसमें वास्तव में एक तत्व है या नहीं।

func allEqualUsingSet<T : Hashable>(array : [T]) -> Bool { 
    let uniqueElements = Set(array) 
    return count(uniqueElements) <= 1 
} 

एक त्वरित बेंच मार्किंग परीक्षण से पता चला कि "शामिल है" विधि "सेट" विधि तुलना में बहुत तेज 1,000,000 पूर्णांकों की एक सरणी के लिए, विशेष रूप से है अगर तत्वों नहीं सब बराबर हैं। यह समझ में आता है क्योंकि जल्द ही लौटता है क्योंकि गैर-मिलान तत्व तत्व मिलता है, जबकि Set(array) हमेशा संपूर्ण सरणी को पार करता है।

इसके अलावा "शामिल" विधियां एक स्पष्ट लूप की तुलना में समान तेज़ या थोड़ा तेज़ हैं।

यहां कुछ सरल बेंचमार्किंग कोड है। निस्संदेह परिणाम सरणी आकार, विभिन्न तत्वों की संख्या और तत्व डेटा प्रकार के साथ भिन्न हो सकते हैं।

func measureExecutionTime<T>(title: String, @noescape f : (() -> T)) -> T { 
    let start = NSDate() 
    let result = f() 
    let end = NSDate() 
    let duration = end.timeIntervalSinceDate(start) 
    println("\(title) \(duration)") 
    return result 
} 

var array = [Int](count: 1_000_000, repeatedValue: 1) 
array[500_000] = 2 

let b1 = measureExecutionTime("using loop ") { 
    return allEqualUsingLoop(array) 
} 

let b2 = measureExecutionTime("using contains") { 
    allEqualUsingContains(array) 
} 

let b3 = measureExecutionTime("using set  ") { 
    allEqualUsingSet(array) 
} 

परिणाम (एक मैकबुक प्रो, रिलीज विन्यास पर):

 
using loop  0.000651001930236816 
using contains 0.000567018985748291 
using set  0.0344770550727844 
array[1_000] = 2 साथ

परिणाम हैं स्विफ्ट 2/Xcode 7 के लिए

 
using loop  9.00030136108398e-06 
using contains 2.02655792236328e-06 
using set  0.0306439995765686 

अद्यतन: स्विफ्ट वाक्यविन्यास में विभिन्न परिवर्तनों के कारण , समारोह अब

func allEqual<T : Equatable>(array : [T]) -> Bool { 
    if let firstElem = array.first { 
     return !array.dropFirst().contains { $0 != firstElem } 
    } 
    return true 
} 

रूप में लिखा है लेकिन अब आप भी यह सरणियों के लिए एक विस्तार पद्धति के रूप में परिभाषित कर सकते हैं:

extension Array where Element : Equatable { 
    func allEqual() -> Bool { 
     if let firstElem = first { 
      return !dropFirst().contains { $0 != firstElem } 
     } 
     return true 
    } 
} 

print([1, 1, 1].allEqual()) // true 
print([1, 2, 1].allEqual()) // false 
+0

एक ही कोशिश कर रहा था ... संकलक जाँच ;-) – Antonio

+0

@Antonio: ठीक है धन्यवाद! –

+0

यदि आप किसी अन्य व्यक्ति को कोशिश करने में रुचि रखते हैं, तो आप 'बराबर' और 'दोहराना' का उपयोग कर सकते हैं: 'array.first.map {बराबर (सरणी, दोहराना (गणना: array.count, repealValue: $ 0))} ?? सच '(यह धीमा है) –

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