स्विफ्ट में रिवर्स रेंज


105

क्या स्विफ्ट में रिवर्स रेंज के साथ काम करने का एक तरीका है?

उदाहरण के लिए:

for i in 5...1 {
  // do something
}

एक अनंत लूप है।

स्विफ्ट के नए संस्करणों में वह कोड संकलित करता है, लेकिन रनटाइम में त्रुटि देता है:

घातक त्रुटि: अपरबाउंड <लोअरबाउंड के साथ रेंज नहीं बना सकते

मुझे पता है कि मैं 1..5इसके बजाय उपयोग कर सकता हूं , गणना कर सकता हूं j = 6 - iऔर jअपने सूचकांक के रूप में उपयोग कर सकता हूं। मैं सोच रहा था कि क्या कुछ और सुपाठ्य था?


इसी तरह के प्रश्न के लिए मेरा उत्तर देखें जो आपकी समस्या को हल करने के 8 तरीके देता है। 3.
इमानो पेटिट

जवाबों:


184

नवीनतम स्विफ्ट 3 के लिए अपडेट (अभी भी स्विफ्ट 4 में काम करता है)

आप reversed()एक सीमा पर विधि का उपयोग कर सकते हैं

for i in (1...5).reversed() { print(i) } // 5 4 3 2 1

या stride(from:through:by:)विधि

for i in stride(from:5,through:1,by:-1) { print(i) } // 5 4 3 2 1

stide(from:to:by:) समान है लेकिन अंतिम मान को शामिल नहीं करता है

for i in stride(from:5,to:0,by:-1) { print(i) } // 5 4 3 2 1

अद्यतन नवीनतम स्विफ्ट 2 के लिए

सबसे पहले, प्रोटोकॉल एक्सटेंशन reverseका उपयोग कैसे किया जाता है:

for i in (1...5).reverse() { print(i) } // 5 4 3 2 1

स्ट्राइड Xcode 7 बीटा 6 में फिर से काम किया गया है। नया उपयोग यह है:

for i in 0.stride(to: -8, by: -2) { print(i) } // 0 -2 -4 -6
for i in 0.stride(through: -8, by: -2) { print(i) } // 0 -2 -4 -6 -8

इसके लिए भी काम करता है Doubles:

for i in 0.5.stride(to:-0.1, by: -0.1) { print(i) }

अस्थायी बिंदु से सावधान रहें सीमा के लिए यहां तुलना करें।

पहले स्विफ्ट 1.2 के लिए संपादित करें : एक्सकोड 6 बीटा 4 के रूप में, और रिवर्सट्रैंग द्वारा अब मौजूद नहीं हैं: [

यदि आप किसी सीमा को उलटना चाह रहे हैं, तो उलटा कार्य करना चाहिए:

for i in reverse(1...5) { println(i) } // prints 5,4,3,2,1

जैसा कि 0x7fffffff द्वारा पोस्ट किया गया है, एक नया स्ट्राइड निर्माण है जिसका उपयोग मध्यस्थ पूर्णांक द्वारा पुनरावृति और वेतन वृद्धि के लिए किया जा सकता है। Apple ने यह भी कहा कि फ्लोटिंग पॉइंट सपोर्ट आ रहा है।

उनके जवाब से खिन्न:

for x in stride(from: 0, through: -8, by: -2) {
    println(x) // 0, -2, -4, -6, -8
}

for x in stride(from: 6, to: -2, by: -4) {
    println(x) // 6, 2
}


1
यह होना चाहिए (1...5).reverse()(एक फ़ंक्शन कॉल के रूप में), कृपया अपना उत्तर अपडेट करें। (चूँकि यह केवल दो अक्षर हैं, मैं आपकी पोस्ट को संपादित नहीं कर सका।)
बेहड़ड

स्विफ्ट 3.0-प्रीव्यू -4 (और संभवतः पहले) में, यह होना चाहिए (1...5).reversed()। इसके अलावा, उदाहरण के लिए .stride()काम नहीं करता है, और stride(from:to:by:)इसके बजाय मुफ्त फ़ंक्शन की आवश्यकता है ।
davidA

2
ऐसा लगता है कि strideस्विफ्ट 3 का कोड थोड़ा गलत है। नंबर 1 को शामिल करने के लिए, आपको इस तरह का throughविरोध करने toकी आवश्यकता होगी :for i in stride(from:5,through:1,by:-1) { print(i) }
262Hz

4
यह इंगित करने के लायक है कि reversedओ (1) की जटिलता है क्योंकि यह केवल मूल संग्रह को लपेटता है और इसे बनाने के लिए एक पुनरावृत्ति की आवश्यकता नहीं है।
devios1

21

इस की विषमता के बारे में कुछ परेशान है:

for i in (1..<5).reverse()

... इसके विपरीत:

for i in 1..<5 {

इसका मतलब है कि हर बार जब मैं एक रिवर्स रेंज करना चाहता हूं, तो मुझे कोष्ठक डालना याद रखना होगा, साथ ही मुझे यह लिखना होगा कि .reverse()अंत में, एक गले में अंगूठे की तरह बाहर चिपके हुए। यह छोरों के लिए सी-शैली की तुलना में वास्तव में बदसूरत है, जो सममित रूप से गिनती और नीचे गिनती कर रहे हैं। इसलिए मैंने लूप्स के बदले C- स्टाइल का इस्तेमाल किया। लेकिन स्विफ्ट 2.2 में, छोरों के लिए सी-स्टाइल दूर जा रहे हैं! तो मुझे इस बदसूरत .reverse()निर्माण के साथ छोरों के लिए मेरे सभी डिक्रीमेंटिंग सी-स्टाइल को बदलने के लिए चारों ओर से घबराना पड़ा है - सभी समय को आश्चर्यचकित करते हुए, पृथ्वी पर रिवर्स रेंज ऑपरेटर क्यों नहीं है?

लेकिन रुकें! यह स्विफ्ट है - हमें अपने स्वयं के ऑपरेटरों को परिभाषित करने की अनुमति है !! ये रहा:

infix operator >>> {
    associativity none
    precedence 135
}

func >>> <Pos : ForwardIndexType where Pos : Comparable>(end:Pos, start:Pos)
    -> ReverseRandomAccessCollection<(Range<Pos>)> {
        return (start..<end).reverse()
}

तो अब मुझे कहने की अनुमति है:

for i in 5>>>1 {print(i)} // 4, 3, 2, 1

यह कवर सिर्फ सबसे सामान्य रूप में है कि मेरे कोड में होता है, लेकिन यह है दूर दूर तक के सर्वाधिक मामले, तो यह वर्तमान में सब मैं ज़रूरत नहीं है।

मुझे ऑपरेटर के साथ एक प्रकार का आंतरिक संकट आ रहा था। मैं इसका उपयोग करना पसंद करूंगा >.., क्योंकि यह उल्टा है ..<, लेकिन यह कानूनी नहीं है: आप एक गैर-डॉट के बाद एक डॉट का उपयोग नहीं कर सकते हैं, ऐसा प्रतीत होता है। मैंने विचार किया ..>लेकिन फैसला किया कि इससे अलग होना बहुत मुश्किल था ..<। अच्छी बात >>>यह है कि यह आप पर चिल्लाता है: " नीचे !" (बेशक आप किसी अन्य ऑपरेटर के साथ आने के लिए स्वतंत्र हैं। लेकिन मेरी सलाह है: सुपर समरूपता के लिए, <<<जो करना है ..<उसे परिभाषित करें , और अब आपको मिल गया है <<<और >>>जो सममित और टाइप करने में आसान है।)


स्विफ्ट 3 संस्करण (Xcode 8 बीज 6):

infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound) ->
    ReversedRandomAccessCollection<CountableRange<Bound>> 
    where Bound : Comparable, Bound.Stride : Integer {
        return (minimum..<maximum).reversed()
}

स्विफ्ट 4 संस्करण (Xcode 9 बीटा 3):

infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound)
    -> ReversedRandomAccessCollection<CountableRange<Bound>>
    where Bound : Comparable & Strideable { 
        return (minimum..<maximum).reversed()
}

स्विफ्ट 4.2 संस्करण (Xcode 10 बीटा 1):

infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound)
    -> ReversedRandomAccessCollection<Range<Bound>>
    where Bound : Strideable { 
        return (minimum..<maximum).reversed()
}

स्विफ्ट 5 संस्करण (Xcode 10.2.1):

infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound)
    -> ReversedCollection<Range<Bound>>
    where Bound : Strideable {
        return (minimum..<maximum).reversed()
}

1
वाह, >>>ऑपरेटर वास्तव में अच्छा है! मुझे उम्मीद है कि स्विफ्ट डिज़ाइनर इस तरह की चीजों पर ध्यान देंगे, क्योंकि reverse()कोष्ठक अभिव्यक्तियों के अंत पर चिपकना अजीब लगता है। कोई कारण नहीं है कि वे 5>..0स्वचालित रूप से सीमाओं से नहीं निपट सकते हैं , क्योंकि ForwardIndexTypeप्रोटोकॉल एक पूरी तरह से उचित distanceTo()ऑपरेटर प्रदान करता है जिसका उपयोग यह पता लगाने के लिए किया जा सकता है कि स्ट्राइड सकारात्मक या नकारात्मक होना चाहिए।
दासब्लिंकलाइटलाइट

1
धन्यवाद @dasblinkenlight - यह मेरे लिए आया क्योंकि मेरे एक ऐप में मैंने लूप्स के लिए बहुत सी (ऑब्जेक्टिव-सी में) की थी जो लूप्स के लिए स्विफ्ट सी-स्टाइल में माइग्रेट हुई थी और अब इसे बदलना पड़ा क्योंकि लूप्स के लिए सी-स्टाइल दूर जा रहे हैं। यह बस भयानक था, क्योंकि इन लूपों ने मेरे ऐप के तर्क के मूल का प्रतिनिधित्व किया, और सब कुछ टूटने के जोखिम को फिर से लिखना। इस प्रकार मैं एक संकेतन चाहता था जो कि (टिप्पणी-आउट) सी-शैली संकेतन के साथ पत्राचार को यथासंभव स्पष्ट कर देगा।
मैट

साफ! मुझे साफ दिखने वाले कोड के साथ आपका जुनून पसंद है!
योहॉस्ट

10

ऐसा प्रतीत होता है कि इस प्रश्न के उत्तर थोड़े बदल गए हैं क्योंकि हमने दांव के माध्यम से प्रगति की है। बीटा 4 के रूप में, by()फ़ंक्शन और ReversedRangeप्रकार दोनों को भाषा से हटा दिया गया है। यदि आप एक उलटी सीमा बनाना चाहते हैं, तो आपके विकल्प अब इस प्रकार हैं:

1: एक फ़ॉरवर्ड रेंज बनाएं, और फिर reverse()इसे रिवर्स करने के लिए फ़ंक्शन का उपयोग करें ।

for x in reverse(0 ... 4) {
    println(x) // 4, 3, 2, 1, 0
}

for x in reverse(0 ..< 4) {
    println(x) // 3, 2, 1, 0
}

2: stride()बीटा 4 में जोड़े गए नए फ़ंक्शंस का उपयोग करें , जिसमें शुरुआती और समाप्ति अनुक्रमित को निर्दिष्ट करने के लिए फ़ंक्शंस शामिल हैं, साथ ही साथ इसे पुनरावृति करने के लिए राशि भी शामिल है।

for x in stride(from: 0, through: -8, by: -2) {
    println(x) // 0, -2, -4, -6, -8
}

for x in stride(from: 6, to: -2, by: -4) {
    println(x) // 6, 2
}

ध्यान दें कि मैंने इस पोस्ट में नए अनन्य रेंज ऑपरेटर को भी शामिल किया है। ..के साथ बदल दिया गया था ..<

संपादित करें: Xcode 6 बीटा 5 रिलीज़ नोटों से , Apple ने इसे संभालने के लिए निम्नलिखित सुझाव जोड़ा:

ReverseRange हटा दिया गया है; आलसी का उपयोग करें (x)

यहाँ एक उदाहरण है।

for i in lazy(0...5).reverse() {
    // 0, 1, 2, 3, 4, 5
}

+1 मैं एक संदर्भ ढूंढ रहा हूं lazy(0....5).reverse()और मुझे बीटा 5 रिलीज़ नोट नहीं दिख रहे हैं। क्या आप इस विषय पर अन्य चर्चाओं के बारे में जानते हैं? इसके अलावा, FYI करें, उस forलूप के अंदर की संख्या आपके उदाहरण में पीछे की ओर है।
रोब

1
@ रोब हम्म मुझे लगा होगा कि एक बीटा के लिए रिलीज नोट्स अंततः नीचे ले जाया जाएगा। जब मैंने यह लिखा था, तो वह एकमात्र स्थान था जिसे मैंने आलसी () के संदर्भ में देखा था, लेकिन मैं ख़ुशी से कुछ और तलाश करूंगा और बाद में घर पहुंचने पर इसे सुधार / सुधार लूंगा। इस पर ध्यान दिलाने के लिए धन्यवाद।
मिक मैक्लम

1
@ 0x7fffffff अपने अंतिम उदाहरण में, टिप्पणी कहती है // 0, 1, 2, 3, 4, 5लेकिन इसे वास्तव में उलट जाना चाहिए। टिप्पणी भ्रामक है।
पंग


3

स्विफ्ट 3, 4+ : आप इसे इस तरह से कर सकते हैं:

for i in sequence(first: 10, next: {$0 - 1}) {

    guard i >= 0 else {
        break
    }
    print(i)
}

परिणाम : 10, 9, 8 ... 0

आप इसे किसी भी तरह से अनुकूलित कर सकते हैं। अधिक जानकारी के लिए संदर्भ पढ़ेंfunc sequence<T>



-2

रिवर्स नंबर के लिए रिवर्स () फ़ंक्शन का उपयोग किया जाता है।

Var n: Int // एंटर नंबर

1 में i के लिए ... n.reverse () {Print (i)}

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.