क्या मैं स्विफ्ट में कथन के साथ रेंज ऑपरेटर का उपयोग कर सकता हूं?


197

क्या रेंज ऑपरेटर का उपयोग करना संभव है ...और ..<यदि स्टेटमेंट के साथ। कुछ इस तरह से:

let statusCode = 204
if statusCode in 200 ..< 299 {
  NSLog("Success")
}

जवाबों:


427

आप "पैटर्न-मैच" ऑपरेटर का उपयोग कर सकते हैं ~=:

if 200 ... 299 ~= statusCode {
    print("success")
}

या एक अभिव्यक्ति पैटर्न के साथ एक स्विच-स्टेटमेंट (जो आंतरिक रूप से पैटर्न-मैच ऑपरेटर का उपयोग करता है):

switch statusCode {
case 200 ... 299:
    print("success")
default:
    print("failure")
}

ध्यान दें कि ..<एक सीमा को दर्शाता है जो ऊपरी मूल्य को छोड़ देता है, इसलिए आप शायद चाहते हैं 200 ... 299या 200 ..< 300

अतिरिक्त जानकारी: जब अनुकूलन के साथ Xcode 6.3 में उपरोक्त कोड संकलित किया जाता है, तो परीक्षण के लिए

if 200 ... 299 ~= statusCode

वास्तव में कोई फ़ंक्शन कॉल बिल्कुल उत्पन्न नहीं होती है, केवल तीन विधानसभा निर्देश:

addq    $-200, %rdi
cmpq    $99, %rdi
ja  LBB0_1

यह ठीक उसी विधानसभा कोड है, जिसके लिए जनरेट किया गया है

if statusCode >= 200 && statusCode <= 299

आप इसे सत्यापित कर सकते हैं

xcrun -sdk macosx स्विफ्ट -O -मिट-असेंबली main.swift

स्विफ्ट 2 के रूप में, यह लिखा जा सकता है

if case 200 ... 299 = statusCode {
    print("success")
}

इफ-स्टेटमेंट्स के लिए नए पेश किए गए पैटर्न-मैचिंग का उपयोग करना। स्विफ्ट 2 भी देखें - "यदि" में पैटर्न मिलान


1
कूल, यह ओ (1) है? इसके अलावा, यह अच्छा होगा अगर स्विफ्ट के पास बयानों के लिए एक छोटा हाथ हो, उदाहरण के लिए स्काला। लेकिन यह देखते हुए कि आप स्विफ्ट में संकलन के समय सभी संभावनाओं को संभालने के लिए मजबूर हैं, यह वास्तव में संभव नहीं है।
स्काई

2
@ सिक: जनरेट असेंबली कोड से कोई देख सकता है कि लाइब्रेरी फंक्शन func ~= (Range<A>, A) -> Boolकहा जाता है। मैं मानूंगा कि यह फ़ंक्शन O (1) के साथ काम करता है।
मार्टिन आर।

4
@Downvoter: कुछ व्याख्या करने वाली टिप्पणी अच्छी लगेगी, ताकि मैं उत्तर को बेहतर बना सकूं या ठीक कर सकूं ...
मार्टिन आर।

1
@MartinR आपको यह कैसे पता चलता है कि किस फ़ंक्शन को असेंबली लैंग्वेज ने कॉल किया है। कूल जवाब के लिए +1
कोडर

3
@ कोड: मैंने xcrun -sdk macosx swift -emit-assembly main.swiftअसेंबली लाइन पर कोड को संकलित किया और विधानसभा कोड का निरीक्षण किया। तब मैं xcrun swift-demangle ...बुलाए गए फ़ंक्शन के नाम को डी-मैन करता था। - दुर्भाग्य से, Xcode अभी तक स्विफ्ट फ़ाइलों के लिए असेंबली कोड नहीं बना सकता है, शायद यह बाद के संस्करण में काम करेगा।
मार्टिन आर।

95

यह संस्करण पैटर्न मिलान से अधिक पठनीय प्रतीत होता है:

if (200 ... 299).contains(statusCode) {
    print("Success")
}

2
बिल्कुल वही जो मैं खोज रहा था
नाज़िम केरीमबकोव

मुझे यह त्रुटि मिलती है => अपरबाउंड के साथ रेंज नहीं बना सकते हैं <निचलाबाउंड
अल्फी

9

यह एक पुराना धागा है, लेकिन मुझे लगता है कि हम इस पर विचार कर रहे हैं। यह मुझे सबसे अच्छा जवाब है बस लगता है

if statusCode >= 200 && statusCode <= 299

वहाँ कोई नहीं

if 200 > statusCode > 299

फ़ॉर्म जो मुझे ज्ञात है, और अन्य सुझाए गए समाधान फ़ंक्शन कॉल कर रहे हैं, जो पढ़ने में कठिन हैं, और निष्पादित करने के लिए धीमी हो सकती हैं। पैटर्न मैच विधि जानने के लिए एक उपयोगी चाल है, लेकिन इस समस्या के लिए एक गरीब फिट की तरह लगता है।

संपादित करें:

व्यक्तिगत रूप से, मुझे लगता है कि पैटर्न मैच ऑपरेटर छुपा हुआ होगा, और इच्छा है कि संकलक if x in 1...100सिंटैक्स का समर्थन करेगा । यह बहुत अधिक सहज और पढ़ने में आसान हैif 1...100 ~= x


1
आप सही हैं कि यह संस्करण पढ़ने के लिए बेहतर है, मैंने बस स्पष्ट प्रश्न का उत्तर देने की कोशिश की "क्या रेंज ऑपरेटर का उपयोग करना संभव है ...?" - लेकिन एक्सकोड 6.3 बीटा (अनुकूलित मोड में) के लिए बिल्कुल तीन विधानसभा निर्देश उत्पन्न करता है if 200 ... 299 ~= statusCode, कोई फ़ंक्शन कॉल नहीं :)
मार्टिन

13
वास्तव if 200 ... 299 ~= statusCodeमें एक ही असेंबली कोड देता हैif statusCode >= 200 && statusCode <= 299
मार्टिन आर

6
जब तक यह सशर्त एक महत्वपूर्ण खंड में है जो प्रति सेकंड हजारों बार जाता है, फ़ंक्शन कॉल ओवरहेड के बारे में चिंता करना समय से पहले अनुकूलन है। फिर भी, मुझे इस बात की अधिक चिंता होगी कि फ़ंक्शन कॉल करने के बजाय इसे कॉल करने की लागत क्या है। अच्छा काम @MartinR साबित करने के लिए कोई कीमत नहीं है, हालांकि।
रिकस्टर

1
@rickster, काफी सच है। मैं अभी भी आदत के मामले में अक्षम लोगों की तुलना में कुशल निर्माणों को प्राथमिकता देता हूं (पठनीयता समान है)। इस हद तक नहीं कि मैं उस पर अपना बहुत अधिक समय बर्बाद करता हूं, लेकिन यह अभी भी यह जानने के लिए भुगतान करता है कि विभिन्न दृष्टिकोणों की लागत क्या है।
डंकन सी

1
यह नाइटपिंगिंग है, लेकिन मैं आपके सुझाव से असहमत हूं कि आपका बयान @SerhiiYakovenko द्वारा पोस्ट किए गए उत्तर की तुलना में अधिक पठनीय या समझने योग्य है। बस DRY के आधार पर - आप दो बार "स्टेटसकोड" नाम देते हैं। देर-रात की धमाकेदार आँखों वाले डिबगिंग सत्र के बाद, मैंने फैसला किया कि "स्टेटसवैल्यू" नामक एक अलग चर का उपयोग "स्टेटसकोड" के बजाय यहाँ किया जाना चाहिए, मैं सिर्फ चर नामों में से एक को बदलने की गलती कर सकता हूँ और दूसरे को नहीं। ।
RenniePet

3

मैं 401 को छोड़कर 4xx त्रुटियों की जाँच करना चाहता था। यहाँ कोड है:

let i = 401

if 400..<500 ~= i, i != 401 {
    print("yes")
} else {
    print("NO")
}

2

मैंने रेंज .contains () ऑपरेटर को भी प्राथमिकता दी, जब तक कि इसका कार्यान्वयन अक्षम न हो जाए - https://oleb.net/blog/2015/09/swift-ranges-and-intervals/

हम एक सीमा का उपयोग करके स्थिति x <0 का प्रतिनिधित्व कर सकते हैं: (Int.min .. <0) .contains (x) बिल्कुल समकक्ष है। हालांकि यह काफी धीमा है। इसमें (_ :) के डिफ़ॉल्ट कार्यान्वयन पूरे संग्रह का पता लगाता है, और सबसे खराब स्थिति में एक लूप नौ क्विंटल बार निष्पादित करना सस्ता नहीं है।

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