2016-01-24 6 views

उत्तर

5

आप इस प्रकार शेष सरणी टुकड़ा पर तत्व के सूचकांक के लिए एक और खोज कर सकते हैं Xcode 9 • स्विफ्ट 4

extension Array where Element: Equatable { 
    func secondIndex(of element: Element) -> Index? { 
     guard let index = index(of: element) else { return nil } 
     return self[self.index(after: index)...].index(of: element) 
    } 
    func indexes(of element: Element) -> [Index] { 
     var indexes: [Index] = [] 
     var position = self.startIndex 
     while let index = self[position...].index(of: element) { 
      indexes.append(index) 
      position = self.index(after: index) 
     } 
     return indexes 
    } 
} 

परीक्षण:

let numbers = [1,3,4,5,5,9,0,1] 
numbers.secondIndex(of: 5)   // 4 
numbers.indexes(of: 5)    // [3,4] 
1

मुझे नहीं लगता कि आप इसे indexOf के साथ कर सकते हैं। इसके बजाय आपको for-loop का उपयोग करना होगा। एक आशुलिपि संस्करण:

संपादित करें/अद्यतन:

let numbers = [1,3,4,5,5,9,0,1] 
var indexes = [Int]() 
numbers.enumerate().forEach { if $0.element == 5 { indexes += [$0.index] } } 

print(indexes) // [3, 4] 
+1

यह बहुत कठिन काम करता है क्योंकि मैं केवल दूसरी घटना को ढूंढना चाहता हूं। मेरी सरणी बड़ी है। –

1

यहां एक सामान्य यू है Array की se विस्तार है कि किसी भी सरणी में एक प्रकार के n वें तत्व को खोजने के लिए काम करेंगे:

extension Array where Element: Equatable { 
    // returns nil if there is no nth occurence 
    // or the index of the nth occurence if there is 
    func findNthIndexOf(n: Int, thing: Element) -> Int? { 
     guard n > 0 else { return nil } 
     var count = 0 
     for (index, item) in enumerate() where item == thing { 
      count += 1 
      if count == n { 
       return index 
      } 
     } 
     return nil 
    } 
} 

let numbers = [1,3,4,5,5,9,0] 

numbers.findNthIndexOf(2, thing: 5) // returns 4 
1

एक बार जब आप पहली घटना पाया है, तो आप सरणी के शेष टुकड़ा पर indexOf उपयोग कर सकते हैं दूसरे का पता लगाने की घटना:

let numbers = [1,3,4,5,5,9,0,1] 

if let firstFive = numbers.indexOf(5) { // 3 
    let secondFive = numbers[firstFive+1..<numbers.count].indexOf(5) // 4 
} 
0

संपादित: @ davecom की टिप्पणी के अनुसार, मैं जवाब के तल पर एक समान है, लेकिन थोड़ा और अधिक जटिल समाधान शामिल किया है।

मैं यहां कुछ अच्छे समाधान देखता हूं, विशेष रूप से स्विफ्ट की अपेक्षाकृत नई भाषा की सीमाओं पर विचार करता हूं। ऐसा करने का एक बहुत ही संक्षिप्त तरीका है, लेकिन सावधान रहें ... यह बल्कि तेज़ और गंदा है। सही समाधान नहीं हो सकता है, लेकिन यह बहुत तेज़ है। बहुत बहुमुखी (ब्रैग नहीं)।

extension Array where Element: Equatable { 
    func indexes(search: Element) -> [Int] { 
     return enumerate().reduce([Int]()) { $1.1 == search ? $0 + [$1.0] : $0 } 
    } 
} 

इस एक्सटेंशन का उपयोग, आप दूसरे सूचकांक इस प्रकार पहुंच सकता है:

let numbers = [1, 3, 4, 5, 5, 9, 0, 1] 
let indexesOf5 = numbers.indexes(5) // [3, 4] 

indexesOf5[1] // 4 

और आप काम हो गया!

असल में, विधि इस तरह काम करती है: enumerate() तत्व के साथ प्रत्येक तत्व की अनुक्रमणिका सहित ट्यूपल्स के लिए सरणी को मानचित्र करता है। इस मामले में, [1, 3, 4, 5, 5, 9, 0, 1].enumerate()EnumerateSequence<Array<Int>> प्रकार का संग्रह देता है, जिसे एक इंटीजर सरणी में अनुवादित किया गया है, [(0,1), (1,3), (2,4), (3,5), (4,5), (5,9), (6,0), (7,1)] देता है।

काम के बाकी reduce (बुलाया कुछ भाषाओं में 'सुई') है, जो कि कई कोडर से परिचित नहीं हैं एक अत्यंत शक्तिशाली उपकरण है उपयोग किया जाता है। यदि पाठक उन कोडर्स में से एक है, तो मैं जेएस में फ़ंक्शन के उपयोग के संबंध में this article की जांच करने की अनुशंसा करता हूं (ध्यान में रखे गए गैर-ब्लॉक तर्क की नियुक्ति को जेएस में ब्लॉक के बाद इनपुट किया गया है, जैसा कि यहां देखा गया है)।

पढ़ने के लिए धन्यवाद।

पीएस इस अपेक्षाकृत सरल समाधान पर बहुत लंबे समय तक नहीं चलने के लिए, लेकिन यदि ऊपर दिखाए गए indexes विधि के लिए सिंटैक्स थोड़ा भी त्वरित और गंदा है, तो आप विधि निकाय में ऐसा कुछ करने का प्रयास कर सकते हैं, जहां बंद करने के पैरामीटर थोड़ा अधिक स्पष्टता के लिए विस्तारित किया जाता है:

return enumerate().reduce([Int]()) { memo, element in 
    element.1 == search ? memo + [element.0] : memo 
} 

संपादित: यहाँ एक अधिक कुशल समाधान के लिए एक और विकल्प है कि implementer एक विशिष्ट "सूचकांक में सूचकांक" के लिए स्कैन करने की अनुमति देता है (उदाहरण के लिए 5 की दूसरी घटना) है।

extension Array where Element: Equatable { 
    func nIndex(search: Element, n: Int) -> Int? { 
     let info = enumerate().reduce((count: 0, index: 0), combine: { memo, element in 
      memo.count < n && element.1 == search ? (count: memo.count + 1, index: element.0) : memo 
     }) 
     return info.count == n ? info.index : nil 
    } 
} 

[1, 3, 4, 5, 5, 9, 0, 1].nIndex(5, n: 2) // 4 
[1, 3, 4, 5, 5, 9, 0, 1].nIndex(5, n: 3) // nil 

नई पद्धति अभी भी पूरे सरणी पर दोहराता है, लेकिन पिछले विधि में "सरणी निर्माण" की कमी के कारण बहुत अधिक कुशल है। वह प्रदर्शन हिट बहुमत के लिए उपयोग की जाने वाली 8-ऑब्जेक्ट सरणी के साथ नगण्य होगी। लेकिन से 10,000 यादृच्छिक संख्या की एक सूची पर विचार 0 से 99:

let randomNumbers = (1...10000).map{_ in Int(rand() % 100)} 

let indexes = randomNumbers.indexes(93) // count -> 100 (in my first run) 
let index1 = indexes[1] // 238 
// executed in 29.6603130102158 sec 

let index2 = randomNumbers.nIndex(93, n: 2) // 238 
// executed in 3.82625496387482 sec 

के रूप में देखा जा सकता है, इस नई विधि काफी तेज (बहुत) बड़े डेटासेट के साथ है; हालांकि यह थोड़ा अधिक बोझिल और भ्रमित है, इसलिए आपके आवेदन के आधार पर, आप सरल समाधान या पूरी तरह से एक अलग पसंद कर सकते हैं।

(फिर से) पढ़ने के लिए धन्यवाद।

+1

इस समाधान के साथ समस्या @ Eendje के साथ समस्या के समान ही है - यदि आप केवल दूसरी घटना चाहते हैं, तो आप अभी भी पूरी सरणी के माध्यम से खोज कर सकते हैं जो संभावित रूप से एक बड़ा प्रदर्शन pitfall है। दूसरे शब्दों में यह ओ (एन) सबसे बुरी स्थिति, औसत मामला, और सबसे अच्छा मामला है जबकि यहां कुछ अन्य समाधान ओ (1) सर्वोत्तम मामले में हैं (यदि आप पहले तत्व या ओ (2 की तलाश में हैं)) यदि आप दूसरे तत्व की तलाश में हैं) और केवल ओ (एन) सबसे खराब मामले में। – davecom

+0

@ डेवॉम यह एक बहुत अच्छा मुद्दा है, लेकिन कुछ मामलों में यह एक बड़ा सौदा नहीं है, और प्रदर्शन हिट डेटा की थोड़ी मात्रा के साथ नगण्य होगी। मैं एक विशिष्ट "इंडेक्स पर इंडेक्स" को अधिक कुशलता से खोजने के लिए एक विकल्प शामिल करने के लिए समाधान अद्यतन करूंगा। – aopsfan

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