2015-08-16 4 views
5

का उपयोग करके ढूंढें() सामान्य रूप से कार्यात्मक प्रोग्रामिंग में उपयोग किया जाने वाला एक सामान्य खोज() बनाना चाहते हैं। कार्यात्मक प्रोग्रामिंग में आप सरणी सूचकांक और लूप के लिए काम नहीं करते हैं। आप फ़िल्टर करते हैं। जिस तरह से यह काम करता है कि यदि आप की एक सूची हैफ़ंक्शनल प्रोग्रामिंग

["apple", "banana", "cherry"] 

कहना है और आप

[(1, "apple"), (2, "banana"), (3, "cherry")] 

अब आप फ़िल्टर कर सकते हैं केले को खोजने के लिए तो आप बनाने tuples द्वारा सूची तत्वों को सरणी सूचकांक सौंपना चाहते हैं "केले" तक और सूचकांक मूल्य वापस करें।

मैं इसके लिए एक सामान्य कार्य बनाने की कोशिश कर रहा था लेकिन मुझे एक त्रुटि मिली। इस वाक्यविन्यास में क्या गलत है?

func findInGenericIndexedList<T>(indexedList: [(index: Int, value: T)], element: (index: Int, value: T)) -> Int? {   
    let found = indexedList.filter { // ERROR: Cannot invoke 'filter' with an argument list of type '((_) -> _)' 

     element.value === $0.value 
    } 

    if let definiteFound = found.first { 
     return definiteFound.index 
    } 
    return nil 
} 

UPDATE 1: मैं ऊपर समाधान के रूप में खोज() (बहिष्कृत कर दिया जाएगा) का उपयोग करने का विरोध किया है क्योंकि मैं कार्यात्मक प्रोग्रामिंग प्रतिमान का पालन करने की कोशिश कर रहा हूँ 2.0 indexOf() का उपयोग करें या स्विफ्ट में चाहते हैं , सामान्य कार्यों पर निर्भर करता है और वर्ग विधियों पर निर्भर नहीं है।

+0

1) 'element === $ 0.value' में आप एक प्रकार के टुपल की तुलना करें '(Int, T) 'प्रकार के मूल्य के साथ' टी'। 2) '===', "समान-से" ऑपरेटर, केवल * कक्षाओं * के उदाहरणों के लिए परिभाषित किया गया है। 3) क्या आप जानते हैं कि स्विफ्ट में पहले से ही 'ढूंढ' समारोह है? (स्विफ्ट 2 में इसे 'इंडेक्सऑफ' कहा जाता है।) –

+1

युक्तियों के लिए धन्यवाद! मैंने अपना प्रश्न अपडेट किया क्यों() indexOf() मेरे पसंदीदा समाधान नहीं हैं। मैंने आपके बिंदु 1 के आधार पर कोड अपडेट किया है। यह समझ में आता है, हालांकि यह अभी भी काम नहीं करता है। यदि '===' पहचान ऑपरेटर ऐसे मामलों में काम नहीं करता है, तो आप इस तरह एक सामान्य कार्य कैसे लिखेंगे? – Daniel

उत्तर

2

इस काम को करने के लिए आवश्यक न्यूनतम परिवर्तन टी को समानता के अनुरूप बनाना होगा और == ऑपरेटर का उपयोग करना होगा।

func findInGenericIndexedList<T:Equatable>(indexedList: [(index: Int, value: T)], element: (index: Int, value: T)) -> Int? { 
    let found = indexedList.filter { 
     element.value == $0.value 
    } 

    if let definiteFound = found.first { 
     return definiteFound.index 
    } 
    return nil 
} 

यह वास्तव में भावना का उपयोग करने के लिए नहीं है === यहाँ क्योंकि आम तौर पर मूल्य प्रकार को यह लागू करने जा करने के लिए (विशेष रूप से यदि आप कार्यात्मक मानदंड का अनुसरण कर रहे) जिसके लिए यह सच नहीं है जा रहे हैं।

इसके अलावा मैं कुछ समय बिताया समस्या के बारे में सोच और यहाँ मैं क्या करना होगा है: 0 अनुक्रमित सरणी पर

extension Array where Element : Equatable { 
    func find(element:Array.Generator.Element) -> Int? { 
     let indexedList = lazy(self.enumerate()) 
     let found = indexedList.filter { 
      element == $1 
     } 

     let definiteFound = found.prefix(1) 
     return definiteFound.generate().next()?.index 
    } 
} 

प्रोटोकॉल विस्तार क्योंकि यह वाक्य रचना neater, हर तत्व की जाँच से बचने के लिए आलसी अनुक्रम बनाता है ।

+0

विस्तृत उत्तर के लिए धन्यवाद। मैं अभी भी पहचान ऑपरेटर '===' का उपयोग करना पसंद करूंगा, क्योंकि मेरी सरणी में मेरे पास एक ही मूल्य के कई आइटम हो सकते हैं। हालांकि, मैं उस कार्य को हटा देना चाहता हूं जिसे मैंने फ़ंक्शन में पास किया था। क्या ऐसा करना असंभव है? (मुझे वास्तव में आपका एक्सटेंशन पसंद है। यह कम कार्यात्मक प्रोग्रामिंग और थोड़ा अधिक ओओ हो सकता है, हालांकि एफपी उच्च ऑर्डर फ़ंक्शंस के साथ अधिक काम करता है। सबकुछ बीत चुका है।) – Daniel

+0

आप "सटीक आइटम" को कैसे परिभाषित करते हैं? क्या एक ही इंडेक्स और एक ही सामग्री वाला आइटम है? यानी, जहां (इंट, स्ट्रिंग) टुपल वही होगा? या आप वास्तव में एक ही सामग्री के साथ कई tuples होने की उम्मीद है? –

+0

@Roman ठीक है आप स्पष्ट रूप से सूचकांक को नहीं जानते होंगे। अन्यथा आप इसे वापस कर सकते हैं। –

1

यहां कुछ विचार दिए गए हैं।

मैं अभी भी पहचान ऑपरेटर '=== "का उपयोग करने के क्योंकि मेरे सरणी में मैं एक ही मूल्य के एक से अधिक आइटम हो सकता है पसंद करेंगे।

पहचान ऑपरेटर === केवल कक्षाओं जैसे संदर्भ प्रकारों के लिए काम करता है। यह मूल्य प्रकारों के लिए कभी भी काम नहीं करेगा, जैसे String एस या Int एस, या struct एस, आदि। आप मूल्य प्रकारों और संदर्भ प्रकारों के बीच अंतर को देख सकते हैं, खासकर यदि आप कार्यात्मक प्रोग्रामिंग में रूचि रखते हैं, जो लगभग संदर्भ प्रकारों को संदर्भित करता है पूरी तरह। जब आप मूल्य प्रकारों के साथ काम कर रहे होते हैं, तो केवल समानता होती है (==) - कोई पहचान नहीं है। String "bananas" के दो उदाहरण कभी भी समान समान वस्तु का संदर्भ नहीं लेंगे। वे हमेशा दो अलग-अलग String एस देखेंगे, हालांकि उनके मानबराबर हो सकते हैं।

मैं फ़ंक्शन में पास की गई सटीक वस्तु को हटाना चाहता हूं। क्या ऐसा करना असंभव है?

यदि आप मूल्य प्रकारों के साथ काम कर रहे हैं, जैसे String एस, तो हाँ, यह असंभव है।दो अलग-अलग String एस जैसी कोई चीज नहीं है जो एक ही वस्तु है। ऊपर बताए गए कारणों के लिए दो String एस हमेशा अलग-अलग वस्तुएं होती हैं।

ध्यान दें कि यदि आप केवल कक्षाओं के साथ काम करते हैं, और मूल्य प्रकार नहीं हैं, तो आप === ऑपरेटर का उपयोग कर सकते हैं, लेकिन इससे आप जो कुछ करने की कोशिश कर रहे हैं उसे पराजित करेंगे।

क्या यह है कि यदि आप (index, value) tuples कि इस तरह दिखता है की एक सरणी के लिए नीचे फोड़े:

[(0, "bananas"), (1, "apples"), (2, "oranges"), (3, "bananas")] 

और आप एक समारोह है कि tuples जहां मूल्य "bananas" है के लिए लग रहा है लिखते हैं, आप एक जोड़ी विकल्पों का आप इसे फ़िल्टर कर सकते हैं और पहले उस सरणी में टुपल देखें, जिसमें "bananas" मान है और उस टुपल की अनुक्रमणिका लौटाएं। उपर्युक्त मामले में यह 0 वापस आ जाएगा। या, आप एरे के रूप में इंडेक्स के सभी वापस कर सकते हैं, जैसे: [0, 3]। या मुझे लगता है कि आप अंतिम इंडेक्स, या पहले-और-अंतिम इंडेक्स आदि जैसे परिणामों के कुछ अन्य मनमाना सबसेट वापस कर सकते हैं, लेकिन वे सभी थोड़ा मूर्ख दिखते हैं। स्विफ्ट मानक लाइब्रेरी पहले आइटम की अनुक्रमणिका को वापस करने का विकल्प चुनती है जो इस कारण से खोज मानदंडों से मेल खाती है। अन्य विकल्पों में से कोई भी पूरी तरह से समझ में नहीं आता है।

लेकिन इसे अपने प्रश्न के संदर्भ में वापस डालने के बाद, "bananas" के मूल्य के साथ आपको मिली कोई भी टुपल "bananas" का सटीक (समान) उदाहरण होने जा रहा है जिसे आपने अपने खोज फ़ंक्शन में पास किया था। कोई भी दो मान प्रकार कभी समान नहीं होते हैं। वे बराबर हो सकते हैं, लेकिन वे कभी भी समान नहीं होते हैं।

एक और नोट - मुख्य रूप से आप जो भी करने की कोशिश कर रहे हैं उसके स्पष्टीकरण के लिए। इस फ़ंक्शन को लिखने के आपके पहले प्रयास में, आप उस आइटम की अनुक्रमणिका को पहले से ही जानते हैं जिसे आप खोज रहे हैं। आप इसे पैरामीटर के रूप में फ़ंक्शन में पास करते हैं, यहां पर:

                 // ----------vvvvv 
func findInGenericIndexedList<T>(indexedList: [(index: Int, value: T)], element: (index: Int, value: T)) -> Int? 

जिज्ञासा से बाहर, क्या यह एक टाइपो है? या क्या आप वास्तव में उस टुपल की अनुक्रमणिका को जानते हैं जिसे आप खोज रहे हैं? क्योंकि यदि आप पहले से ही जानते हैं कि यह क्या है, तो ... आपको इसकी खोज करने की आवश्यकता नहीं है :)

+0

हां, यह एक टाइपो है। :) मुझे केवल तत्व पास करना चाहिए। विस्तृत उत्तर के लिए फिर से धन्यवाद। मुझे आश्चर्य है कि आप समान संदर्भ की तलाश नहीं कर सकते हैं। आदिम प्रकार, स्ट्रिंग्स, जटिल प्रकार, उनके सभी के संदर्भ हैं। यहां तक ​​कि अपरिवर्तनीय भी। मैं स्वीकार करता हूं कि आप ऐसा नहीं कर सकते लेकिन मुझे अभी भी समझ में नहीं आता है। मैं यह क्यों नहीं देख सकता कि कोई ऑब्जेक्ट/आदिम प्रकार/किसी भी प्रकार का एक ही संदर्भ है, "मैं अपने हाथ में पकड़ रहा हूं" (यानी, पैरामीटर के रूप में पारित किया गया है)? – Daniel

+0

यह स्विफ्ट की एक भाषा विशेषता है। मान प्रकार सुरक्षित हैं, क्योंकि एक उदाहरण बदलना हर दूसरे उदाहरण को "संदर्भित" नहीं करता है। मूल्य प्रकार और संदर्भ प्रकार दोनों अपने तरीके से मूल्यवान हैं। –

+0

यह समझ में आता है। माना। – Daniel

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