2016-05-24 13 views
5

मैं अपने इनपुट अनुक्रम के हिस्से का मूल्यांकन करने के बाद उच्च स्तरीय फ़ंक्शन को रोकने का एक तरीका ढूंढ रहा हूं।क्या उच्च-स्तरीय फ़ंक्शन का संक्षिप्त मूल्यांकन करना संभव है?

एक स्थिति पर विचार करें जब आप किसी अनुक्रम में पहली अनुक्रमणिका की तलाश करते हैं जो किसी निश्चित स्थिति को पूरा करता है।

func firstAbove100(a:[Int]) -> Int? { 
    if a.count < 2 { 
     return nil 
    } 
    for i in 0..<a.count-1 { 
     if a[i]+a[i+1] > 100 { 
      return i 
     } 
    } 
    return nil 
} 
: उदाहरण के लिए, मान लीजिए कि हम एक सरणी में प्रथम स्थान के लिए देख रहे Int की a रों जहां लगातार दो मानों का योग से ऊपर 100

तुम एक पाश के साथ यह कर सकते हैं, इस तरह है चलो

जैसे ही ब्याज की स्थिति की खोज की जाती है, लूपिंग बंद हो जाती है।

func firstAbove100(a:[Int]) -> Int? { 
    if a.count < 2 { 
     return nil 
    } 
    return (0..<a.count-1).reduce(nil) { prev, i in 
     prev ?? (a[i]+a[i+1] > 100 ? i : nil) 
    } 
} 

हालांकि, इस दृष्टिकोण का नुकसान यह है कि reduce सब a.count-2 के लिए रास्ता भले ही वह बहुत पहले सूचकांक में एक मैच पाता चला जाता है:

हम इस कोड का उपयोग कर reduce इस प्रकार पुनर्लेखन कर सकते हैं। नतीजा एक जैसा होगा, लेकिन अनावश्यक काम में कटौती करना अच्छा होगा।

क्या reduce बनाने के लिए कोई तरीका है आगे के मैचों की कोशिश करना बंद करें, या शायद एक अलग फ़ंक्शन जो आपको पहले मैच को ढूंढने के बाद रोकने देता है?

+0

@paulvs क्योंकि यह कॉपी-पेस्ट गलत हो गया है :-) धन्यवाद! – dasblinkenlight

+2

मुझे नहीं लगता कि 'कम करने' के साथ ऐसा करने का कोई भी अंतर्निहित तरीका है। 'कम करने' का पूरा बिंदु यह है कि यह * पूरे * अनुक्रम को जोड़ता है और मूल्यांकन करता है। इस विशिष्ट उपयोग के मामले के लिए, आपको शायद अपना खुद का फ़ंक्शन लिखना होगा, जैसा कि आपने अपने पहले कोड ब्लॉक में किया था। –

+1

'कम करें' सिर्फ एक 'के लिए' है जो अगले पुनरावृत्ति के लिए एक मूल्य गुजर रहा है। यदि आप शॉर्ट सर्किटिंग चाहते हैं, तो आपको इसका समर्थन करने वाले उच्च ऑर्डर फ़ंक्शन का उपयोग करना होगा। या 'कम करें' का अपना संस्करण लिखें। इस मामले में मुझे लगता है कि 'कम करने' का उपयोग करना बहुत खराब विकल्प है क्योंकि आप वास्तव में जमाकर्ता का उपयोग नहीं कर रहे हैं। – Sulthan

उत्तर

4

जैसा कि पहले ही कहा, reduce विशेष रूप से आदेश एक पूरे अनुक्रम का मूल्यांकन करने में बनाया गया है और इसलिए करने के लिए डिज़ाइन नहीं शार्ट सर्किट। किसी दिए गए अनुमान को पूरा करने वाले तत्व की अनुक्रमणिका ढूंढने के लिए इस तरह से इसका उपयोग indexOf@Casey says के साथ किया जाता है।

स्विफ्ट 3 के रूप में, अब फ़ंक्शन Sequence पर फ़ंक्शन है जो आपको पहले तत्व को खोजने की अनुमति देता है जो किसी दिए गए अनुमान को पूरा करता है। यह indexOf से भी अधिक उपयुक्त विकल्प हो सकता है, क्योंकि यह सूचकांक के बजाय तत्व लौटाता है (हालांकि आपके विशेष उदाहरण में ये वही हैं)। अगर यह किसी दिए गए विधेय के एक गैर शून्य परिणाम पाता है अगर आप एक अधिक सामान्य उच्च स्तरीय समारोह है कि एक दृश्य के माध्यम से पुनरावृति और बाहर टूट जाएगा चाहते

func firstAbove100(_ a:[Int]) -> Int? { 
    guard a.count > 1 else {return nil} 

    return (0..<a.count-1).first { i in 
     a[i]+a[i+1] > 100 
    } 
} 

हालांकि:

आप इस तरह अपने उदाहरण लिख सकता है - आप हमेशा अपनी खुद की find समारोह लिख सकते हैं:

extension SequenceType { 

    func find<T>(@noescape predicate: (Self.Generator.Element) throws -> T?) rethrows -> T? { 
     for element in self { 
      if let c = try predicate(element) {return c} 
     } 
     return nil 
    } 
} 

अब आप इस तरह अपने firstAbove100 समारोह लिख सकते हैं:

func firstAbove100(a:[Int]) -> Int? { 
    if a.count < 2 { 
     return nil 
    } 
    return (0..<a.count-1).find { i in 
     a[i]+a[i+1] > 100 ? i : nil 
    } 
} 

और कहीं भी होगी अब शॉर्ट सर्किट जब यह तत्व है कि ऊपर 100

में जोड़ने के लिए या के बजाय तुलना में अधिक के लिए जोड़ अपने सरणी में तत्वों की पहली जोड़ी के सूचकांक लौटने का मान लीजिए की एक जोड़ी पाता है 100, अब आप तत्वों के योग को वापस करना चाहते हैं।अब आप इस तरह यह लिख सकते हैं:

func sumOfFirstAbove100(a:[Int]) -> Int? { 
    guard a.count > 1 else {return nil} 
    return (0..<a.count-1).find { i in 
     let sum = a[i]+a[i+1] 
     return sum > 100 ? sum : nil 
    } 
} 

let a = [10, 20, 30, 40, 50, 60, 70, 80, 90] 
print(sumOfFirstAbove100(a)) // prints: Optional(110) 

find समारोह, सरणी के माध्यम से पुनरावृति जाएगा प्रत्येक तत्व के लिए विधेय को लागू करने (इस मामले में अपने सरणी के सूचकांक)। यदि भविष्यवाणी nil लौटाती है, तो यह फिर से चलती रहेगी। यदि भविष्यवाणी गैर-शून्य लौटाती है, तो यह उस परिणाम को वापस कर देगा और पुनरावृत्ति को रोक देगा।

4

indexOf यह पहला मैच पाता है के बाद बंद हो जाएगा तो आप कुछ इस तरह के firstAbove100 पुनर्लेखन सकता है:

func firstAbove100(a:[Int]) -> Int? { 
    return a.count > 1 ? (a.startIndex..<a.endIndex-1).indexOf({ a[$0] + a[$0 + 1] > 100 }) : nil 
} 
संबंधित मुद्दे