2017-07-26 23 views
10

दोनों Array और DictionaryforEach(_:) उदाहरण तरीकों में दस्तावेज के रूप में:के लिए उपयोग करने के लिए कब (_ :) के लिए उपयोग करना है?

एक के लिए में पाश के रूप में ही क्रम में अनुक्रम में प्रत्येक तत्व पर दिए गए बंद के कॉल करता है।

फिर भी, Sequence Overview से अनुकूलित:

एक अनुक्रम मूल्यों है कि आप एक समय में एक के माध्यम से कदम कर सकते हैं की एक सूची है। अनुक्रम के तत्वों पर पुनरावृत्त करने के लिए सबसे आम तरीका फॉर-इन लूप का उपयोग करना है।

यह बताना कि forEach(_:) या for in द्वारा अनुक्रम पुनरावृत्ति:

let closedRange = 1...3 

for element in closedRange { print(element) } // 1 2 3 

closedRange.forEach { print($0) } // 1 2 3 

या (सरणी):

let array = [1, 2, 3] 

for element in array { print(element) } // 1 2 3 

array.forEach { print($0) } // 1 2 3 

चाहेंगे एक ही उत्पादन देता है।

क्यों forEach(_:) भी मौजूद है? यानी for in लूप के बजाय इसका उपयोग करने का क्या फायदा है? क्या वे प्रदर्शन बिंदु दृश्य से समान होंगे?

एक धारणा के रूप में, यह कार्यात्मक प्रोग्रामिंग के साथ काम करते समय विशेष रूप से एक वाक्य रचनात्मक चीनी हो सकता है।

+0

प्रदर्शन दृष्टिकोण से 'forEach' ** मीटर यू खो ज ** एक' loop' के लिए की तुलना में धीमी है। लेकिन इसका उद्देश्य उद्देश्य-सी के 'मेकऑब्जेक्ट्सफॉर्मफॉर्मर:' – vadian

+2

@vadian के बराबर आसानी से उपयोग किया जा सकता है - डीबग में यह बहुत धीमा बनाता है। रिलीज बिल्ड में जरूरी नहीं है (स्पष्ट रूप से आपके कोड में अन्य चीजों के आधार पर)। उदाहरण के लिए, मैंने रिलीज बिल्ड में लाखों ऑब्जेक्ट्स के साथ सरणी के माध्यम से पुनरावृत्तियों को बेंचमार्क किया और प्रदर्शन अंतर अलग-अलग था। – Rob

+0

@Rob प्रतिक्रिया के लिए धन्यवाद। दरअसल मेरे "बेंचमार्क टेस्ट" डीबग मोड में किए गए थे (केवल प्रोजेक्ट को देखकर) – vadian

उत्तर

15

forEach द्वारा प्रदान किए जाने वाले कोई प्रदर्शन लाभ नहीं है। वास्तव में, if you look at the source code, forEach फ़ंक्शन वास्तव में बस for - in प्रदर्शन करता है। रिलीज के निर्माण के लिए, for - in का उपयोग करके इस फ़ंक्शन का प्रदर्शन ओवरहेड स्वयं असीमित है, हालांकि डिबग बिल्ड के लिए, इसका परिणाम देखने योग्य प्रदर्शन प्रभाव में होता है।

forEach का मुख्य लाभ एहसास हुआ है कि जब आप कार्यात्मक प्रोग्रामिंग कर रहे हैं, तो आप इसे एक अलग चर में सहेजने के बिना कार्यात्मक कॉल की एक श्रृंखला में जोड़ सकते हैं, यदि आपको for का उपयोग करने की आवश्यकता होगी - in वाक्यविन्यास। तो, के बजाय:

let objects = array.map { ... } 
    .filter { ... } 

for object in objects { 
    ... 
} 

आप के बजाय कार्यात्मक प्रोग्रामिंग पैटर्न के भीतर रहने के कर सकते हैं:

array.map { ... } 
    .filter { ... } 
    .forEach { ... } 

परिणाम कार्यात्मक कोड है कि कम वाक्यात्मक शोर के साथ अधिक संक्षिप्त है।

Fwiw, Array, Dictionary के लिए प्रलेखन, और Sequence सभी सीमाओं forEach द्वारा शुरू की याद दिलाती है, अर्थात्:

  1. आप एक break या continue कथन का उपयोग नहीं कर सकते हैं वर्तमान कॉल बाहर निकलने के लिए body बंद या बाद की कॉल छोड़ें।

  2. body बंद में return बयान का उपयोग करते हुए किसी भी बाहरी दायरे से नहीं body को वर्तमान कॉल से केवल बाहर निकल जाएगा, और आगामी कॉल को नहीं छोड़ेगा।

+0

धन्यवाद @Rob। क्या इसका मतलब यह है कि हमें केवल कार्यात्मक प्रोग्रामिंग के साथ 'फोर्सह' के साथ जाना चाहिए? –

+0

मैं अब तक नहीं कहूंगा कि किसी को कार्यात्मक प्रोग्रामिंग के साथ संयोजन में इसका उपयोग करना चाहिए। यह एक अच्छा संक्षिप्त वाक्यविन्यास है जिसे आप जहां भी चाहें उपयोग कर सकते हैं।मैं केवल यह सुझाव दे रहा था कि इसकी सबसे बड़ी उपयोगिता तब होती है जब कार्यात्मक प्रोग्रामिंग के संयोजन के साथ प्रयोग किया जाता है, जहां 'for'-'in' पैटर्न वास्तव में काफी बोझिल हो जाता है। – Rob

+0

@Rob आपके सुझाव के अनुसार, मैंने इस से संबंधित एक व्युत्पन्न प्रश्न पोस्ट किया है। https://stackoverflow.com/questions/47743259/use-foreach-to-nil-out-values-in-an-array – Adrian

-2

वे कम या ज्यादा परस्पर विनिमय कर रहे है, लेकिन वहाँ दो महत्वपूर्ण मतभेद हैं।

  1. break/continue केवल forEach में एक for .. in
  2. return में काम बंद होने से बाहर हो जाएंगे, लेकिन यात्रा को रोकने के नहीं होंगे।

इस का कारण यह है कि for .. in भाषा में एक विशेष रूप (जो तोड़ने के लिए और आपकी अपेक्षा के अनुरूप काम करना जारी की अनुमति देता है) है। यह ऐसा कुछ है जिसे आप भाषा का उपयोग करके एक समान तरीके से लागू नहीं कर सकते हैं।

हालांकि, forEach एक विशेष रूप नहीं है और इसे एक समारोह के रूप में लिखकर समान रूप से फिर से कार्यान्वित किया जा सकता है।

extension Sequence { 
    func myOwnForEach(_ body: (Self.Element) throws -> Void) rethrows { 
     let it = Self.makeIterator() 
     while let item = it.next() { 
      body(item) 
     } 
    } 
} 
3

मैं हाल ही में एक प्रयोग मामले में जहां forEach का उपयोग कर for in करने के लिए एक ठोस तरह से बेहतर था भर में भाग गया। मान लें कि आप एक परत से सभी sublayers को हटाना चाहते हैं। इस तरह के नीचे के रूप में एक बयान के रूप में आप sublayers नहीं के बराबर हैं, तो आप एक दुर्घटना मिल जाएगा [CALayer]

for layer in self.videoContainerView.layer.sublayers! 

खोलने की जरूरत है काम नहीं करता। यह आपको यह देखने के लिए मजबूर करता है कि पहले sublayers हैं या नहीं। हालांकि, एक forEach इतना निम्नलिखित में के रूप में सरल बनाता है:

self.videoContainerView.layer.sublayers?.forEach { $0.removeFromSuperlayer() } 
संबंधित मुद्दे