स्विफ्ट में एक स्ट्रिंग से पहले चरित्र को हटाने का सबसे रसीला तरीका क्या है?


122

मैं पहले चरित्र को एक स्ट्रिंग से हटाना चाहता हूं। अब तक, सबसे रसीली चीज जो मैं लेकर आया हूं:

display.text = display.text!.substringFromIndex(advance(display.text!.startIndex, 1))

मुझे पता है कि हम Intयूनिकोड के कारण एक स्ट्रिंग में अनुक्रमित नहीं कर सकते हैं , लेकिन यह समाधान भयानक रूप से क्रिया लगता है। वहाँ एक और तरीका है कि मैं देख रहा हूँ?


3
वास्तव में आप NSString को advanceकास्टिंग करके पूरी बात से बच सकते हैं display.text!। मैं यह नहीं कह रहा हूं कि यह एक अच्छा समाधान है - बस एक गलत धारणा को सुधारना। NSString के साथ, आप इसे Int के साथ अनुक्रमित कर सकते हैं । - और जिस कारण से आप Int के साथ अनुक्रमण नहीं कर सकते, वह यूनिकोड के कारण नहीं है; ऐसा इसलिए है क्योंकि एक वर्ण में कई यौगिक कोडपॉइंट हो सकते हैं।
मैट

यदि आपका ऐसा करने के लिए Stringतत्कालीन स्विफ्ट 3 को कैपिटल करने के लिए capitalizedफ़ंक्शन शुरू किया है String
विंस ओ'सूलीवन

जवाबों:


208

यदि आप स्विफ्ट 3 का उपयोग कर रहे हैं , तो आप इस उत्तर के दूसरे भाग को अनदेखा कर सकते हैं। अच्छी खबर है, यह अब वास्तव में फिर से सफल है! स्ट्रिंग के नए हटाने (पर :) विधि का उपयोग करके।

var myString = "Hello, World"
myString.remove(at: myString.startIndex)

myString // "ello, World"

मुझे इसके लिए वैश्विक dropFirst()समारोह पसंद है ।

let original = "Hello" // Hello
let sliced = dropFirst(original) // ello

यह छोटा, स्पष्ट है, और किसी भी चीज़ के लिए काम करता है जो स्लीसेबल प्रोटोकॉल के अनुरूप है।

यदि आप स्विफ्ट 2 का उपयोग कर रहे हैं , तो यह उत्तर बदल गया है। आप अभी भी ड्रॉपफ़र्स्ट का उपयोग कर सकते हैं, लेकिन अपनी स्ट्रिंग्स की charactersसंपत्ति से पहले चरित्र को छोड़ने के बिना नहीं और फिर परिणाम को स्ट्रिंग में परिवर्तित करना। dropFirst भी एक विधि बन गई है, एक फ़ंक्शन नहीं।

let original = "Hello" // Hello
let sliced = String(original.characters.dropFirst()) // ello

एक और विकल्प स्ट्रिंग के विभाजन के लिए प्रत्यय फ़ंक्शन का उपयोग करना है UTF16View। बेशक, इसे बाद में स्ट्रिंग में भी परिवर्तित करना होगा।

let original = "Hello" // Hello
let sliced = String(suffix(original.utf16, original.utf16.count - 1)) // ello

यह सब कहना है कि मूल रूप से मैंने जो समाधान प्रदान किया है वह स्विफ्ट के नए संस्करणों में ऐसा करने का सबसे रसीला तरीका नहीं है। removeAtIndex()यदि आप एक छोटे और सहज समाधान की तलाश कर रहे हैं, तो मैं @chris समाधान पर वापस गिरने की सलाह देता हूं ।

var original = "Hello" // Hello
let removedChar = original.removeAtIndex(original.startIndex)

original // ello

और जैसा कि नीचे टिप्पणी में @vacawama द्वारा बताया गया है, मूल स्ट्रिंग को संशोधित नहीं करने वाला एक अन्य विकल्प है, जो विकल्प स्ट्रिंगफ्रेमइंडेक्स का उपयोग करना है।

let original = "Hello" // Hello
let substring = original.substringFromIndex(advance(original.startIndex, 1)) // ello

या यदि आप स्ट्रिंग के आरंभ और अंत से एक चरित्र को छोड़ने के लिए देख रहे हैं, तो आप substringWithRange का उपयोग कर सकते हैं। बस जब हालत के खिलाफ गार्ड होना सुनिश्चित करें startIndex + n > endIndex - m

let original = "Hello" // Hello

let newStartIndex = advance(original.startIndex, 1)
let newEndIndex = advance(original.endIndex, -1)

let substring = original.substringWithRange(newStartIndex..<newEndIndex) // ell

अंतिम पंक्ति को सबस्क्रिप्ट नोटेशन का उपयोग करके भी लिखा जा सकता है।

let substring = original[newStartIndex..<newEndIndex]

2
और यह आपको फाउंडेशन की दुनिया में कदम रखने की आवश्यकता नहीं है।
मैट

2
और यह बहुत तेज / fp है।
डेविड बेरी

धन्यवाद, यह बहुत अधिक सुरुचिपूर्ण है। मैं सालों से Objective C में प्रोग्रामिंग कर रहा हूं और Swift में iTunes U Stanford iOS प्रोग्रामिंग कोर्स कर रहा हूं। मेरे पास अभी भी नए प्रतिमान के बारे में बहुत कुछ है।
SSteve

1
ड्रॉपलैस्ट या ड्रॉपफर्स्ट का उपयोग करते समय ध्यान रखें, स्ट्रिंग को अनचेक करें अन्यथा यह काम नहीं करेगा।
भावुक जैन

3
बहुत बढ़िया जवाब! मुझे लगता है कि यह remove(at:)विधि के रिटर्न मूल्य को ध्यान देने योग्य है : यह हटाए गए चरित्र है, न कि नया स्ट्रिंग। उदाहरण के लिए, let removedCharacter = myString.remove(at: myString.startIndex)। मैं विधि कॉल के परिणाम को वापस करने की गलती कर रहा था, यह भूल गया कि इस दृष्टिकोण में मामला था। सभी को मुबारक!
kbpontius

118

स्विफ्ट 4 के लिए अपडेट

स्विफ्ट 4 में, फिर से Stringअनुरूप है Collection, इसलिए स्ट्रिंग्स की शुरुआत और छोर को ट्रिम करना dropFirstऔर उपयोग करना संभव है dropLast। परिणाम प्रकार का है Substring, इसलिए आपको पास करने के लिए Stringनिर्माणकर्ता को पास करना होगा String:

let str = "hello"
let result1 = String(str.dropFirst())    // "ello"
let result2 = String(str.dropLast())     // "hell"

dropFirst()और ड्रॉप करने के लिए वर्णों की संख्या निर्दिष्ट करने के लिए dropLast()भी एक लें Int:

let result3 = String(str.dropLast(3))    // "he"
let result4 = String(str.dropFirst(4))   // "o"

यदि आप स्ट्रिंग में हैं की तुलना में ड्रॉप करने के लिए अधिक वर्ण निर्दिष्ट करते हैं, तो परिणाम रिक्त स्ट्रिंग ( "") होगा।

let result5 = String(str.dropFirst(10))  // ""

स्विफ्ट 3 के लिए अपडेट

यदि आप केवल पहले चरित्र को हटाना चाहते हैं और मूल स्ट्रिंग को जगह में बदलना चाहते हैं, तो @ मिकमैकल्लम का उत्तर देखें। यदि आप प्रक्रिया में एक नया स्ट्रिंग बनाना चाहते हैं, तो उपयोग करें substring(from:)। एक विस्तार के साथ करने के लिए String, आप की कुरूपता को छुपा सकते हैं substring(from:)और substring(to:)शुरू करने और एक के सिरों ट्रिम करने के लिए उपयोगी बनाने के लिए अतिरिक्त String:

extension String {
    func chopPrefix(_ count: Int = 1) -> String {
        return substring(from: index(startIndex, offsetBy: count))
    }

    func chopSuffix(_ count: Int = 1) -> String {
        return substring(to: index(endIndex, offsetBy: -count))
    }
}

"hello".chopPrefix()    // "ello"
"hello".chopPrefix(3)   // "lo"

"hello".chopSuffix()    // "hell"
"hello".chopSuffix(3)   // "he"

उनके पहले dropFirstऔर dropLastबाद की तरह , ये फ़ंक्शन क्रैश हो जाएंगे यदि स्ट्रिंग में पर्याप्त पत्र उपलब्ध नहीं हैं। फोन करने वाले को ठीक से उपयोग करने के लिए ओनस है। यह एक वैध डिजाइन निर्णय है। कोई उन्हें एक वैकल्पिक लौटाने के लिए लिख सकता है, जिसे कॉल करने वाले को अलिखित करना होगा।


स्विफ्ट 2.x

स्विफ्ट 2 में काश , dropFirstऔर dropLast(पिछले सबसे अच्छे समाधान) पहले की तरह सुविधाजनक नहीं हैं। के विस्तार के साथ String, आप की बदसूरती छिपा सकते हैं substringFromIndexऔर substringToIndex:

extension String {
    func chopPrefix(count: Int = 1) -> String {
         return self.substringFromIndex(advance(self.startIndex, count))
    }

    func chopSuffix(count: Int = 1) -> String {
        return self.substringToIndex(advance(self.endIndex, -count))
    }
}

"hello".chopPrefix()    // "ello"
"hello".chopPrefix(3)   // "lo"

"hello".chopSuffix()    // "hell"
"hello".chopSuffix(3)   // "he"

उनके पहले dropFirstऔर dropLastबाद की तरह , ये फ़ंक्शन क्रैश हो जाएंगे यदि स्ट्रिंग में पर्याप्त पत्र उपलब्ध नहीं हैं। फोन करने वाले को ठीक से उपयोग करने के लिए ओनस है। यह एक वैध डिजाइन निर्णय है। कोई उन्हें एक वैकल्पिक लौटाने के लिए लिख सकता है, जिसे कॉल करने वाले को अलिखित करना होगा।


में स्विफ्ट 1.2 , आप कॉल करने की आवश्यकता होगी chopPrefixइस तरह:

"hello".chopPrefix(count: 3)  // "lo"

या आप _पैरामीटर नाम को दबाने के लिए फ़ंक्शन परिभाषाओं में एक अंडरस्कोर जोड़ सकते हैं :

extension String {
    func chopPrefix(_ count: Int = 1) -> String {
         return self.substringFromIndex(advance(self.startIndex, count))
    }

    func chopSuffix(_ count: Int = 1) -> String {
        return self.substringToIndex(advance(self.endIndex, -count))
    }
}

3
मैं अभी भी उड़ा रहा हूं कि स्विफ्ट की अंतर्निहित स्ट्रिंग हेरफेर कितनी जटिल है। मेरा मतलब है कि यह बुनियादी, बुनियादी सामान है; ऐसा नहीं लगना चाहिए कि मैं किसी पार्सर को लागू कर रहा हूं। इसे सरल बनाने के लिए विस्तार के लिए धन्यवाद। यह चौंकाने वाला है Apple इसे स्ट्रिंग वर्ग में नहीं जोड़ा जाएगा! शायद यह अभी भी बहुत अधिक प्रवाह में है।
devios1

इसे वे "विकासवादी" बच्चे कहते हैं। यह प्रफुल्लित करने वाला होगा अगर हमें हर दिन इससे नहीं निपटना है। मुझे पता है कि स्ट्रिंग एपीआई के होने के कारण हैं, लेकिन वास्तव में, यह इस भाषा के लिए कई संभावित धर्मान्तरित बंद करना चाहिए। पिछला टिप्पणीकार बिल्कुल सही है - यह मूल, बुनियादी सामान होना चाहिए।
क्विंटिन विल्सन

17

स्विफ्ट 2.2

'एडवांस' अनुपलब्ध है: इंडेक्स पर 'एडवांस्डबी (एन)' विधि को कॉल करें

    func chopPrefix(count: Int = 1) -> String {
        return self.substringFromIndex(self.startIndex.advancedBy(count))
    }

    func chopSuffix(count: Int = 1) -> String {
        return self.substringFromIndex(self.endIndex.advancedBy(count))
    }

स्विफ्ट 3.0

    func chopPrefix(_ count: Int = 1) -> String {
        return self.substring(from: self.characters.index(self.startIndex, offsetBy: count))
    }

    func chopSuffix(_ count: Int = 1) -> String {
       return self.substring(to: self.characters.index(self.endIndex, offsetBy: -count))
    }

स्विफ्ट 3.2

वर्णों के संग्रह के रूप में स्ट्रिंग की सामग्री का एक दृश्य।

@available(swift, deprecated: 3.2, message: "Please use String or Substring directly")
public var characters: String.CharacterView
func chopPrefix(_ count: Int = 1) -> String {
    if count >= 0 && count <= self.count {
        return self.substring(from: String.Index(encodedOffset: count))
    }
    return ""
}

func chopSuffix(_ count: Int = 1) -> String {
    if count >= 0 && count <= self.count {
        return self.substring(to: String.Index(encodedOffset: self.count - count))
    }
    return ""
}

स्विफ्ट 4

extension String {

    func chopPrefix(_ count: Int = 1) -> String {
        if count >= 0 && count <= self.count {
            let indexStartOfText = self.index(self.startIndex, offsetBy: count)
            return String(self[indexStartOfText...])
        }
        return ""
    }

    func chopSuffix(_ count: Int = 1) -> String {
        if count >= 0 && count <= self.count {
            let indexEndOfText = self.index(self.endIndex, offsetBy: -count)
            return String(self[..<indexEndOfText])
        }
        return ""
    }
}

1
मुझे लगता है कि आप चोप्सफिक्स फ़ंक्शन में नकार को जोड़ना भूल गए
एंडी


10

इस पर निर्भर करता है कि आप क्या चाहते हैं कि अंतिम परिणाम (उत्परिवर्तन बनाम नॉनम्यूटेटिंग) हो।

स्विफ्ट 4.1 के रूप में:

स्वचालित रूप से परिवर्तित:

var str = "hello"
str.removeFirst() // changes str 

Nonmutating:

let str = "hello"
let strSlice = str.dropFirst() // makes a slice without the first letter
let str2 = String(strSlice)

टिप्पणियाँ:

  • मैंने nonmutatingस्पष्टता के लिए उदाहरण में एक अतिरिक्त कदम रखा । विशेष रूप से, अंतिम दो चरणों का संयोजन अधिक संक्षिप्त होगा।
  • नामकरण dropFirstमुझे थोड़ा अजीब लगता है क्योंकि अगर मैं स्विफ्ट एपीआई डिजाइन दिशानिर्देशों को सही ढंग से समझ रहा हूं , dropFirstतो वास्तव में ऐसा कुछ होना चाहिए dropingFirstक्योंकि यह नॉनम्यूटेटिंग है। सिर्फ एक विचार :)।

1
वास्तव में, यह होना चाहिए droppingFirst- उन्होंने गड़बड़ कर दी!
फत्ती

6

इस बारे में क्या?

s.removeAtIndex(s.startIndex)

यह निश्चित रूप से मानता है कि आपका स्ट्रिंग परस्पर है। यह उस चरित्र को लौटाता है जिसे हटा दिया गया है, लेकिन मूल स्ट्रिंग को बदल देता है।


6

पिछले उत्तर बहुत अच्छे हैं, लेकिन आज तक, मुझे लगता है कि स्विफ्ट 4 में एक स्ट्रिंग से पहले चरित्र को हटाने के लिए यह सबसे रसीला तरीका हो सकता है :

var line: String = "This is a string..."
var char: Character? = nil

char = line.removeFirst()

print("char = \(char)")  // char = T
print("line = \(line)")  // line = his is a string ...

1

मुझे कुछ भी नहीं पता है कि यह बॉक्स से बाहर है, लेकिन आप आसानी से उपसर्ग को लागू कर सकते हैं ++, जैसे,

public prefix func ++ <I: ForwardIndexType>(index: I) -> I {
    return advance(index, 1)
}

जिसके बाद आप इसे अपने दिल की सामग्री के लिए बहुत आसानी से उपयोग कर सकते हैं:

str.substringFromIndex(++str.startIndex)

1

स्विफ्ट 2 में इस स्ट्रिंग एक्सटेंशन का उपयोग करें:

extension String
{
    func substringFromIndex(index: Int) -> String
    {
        if (index < 0 || index > self.characters.count)
        {
            print("index \(index) out of bounds")
            return ""
        }
        return self.substringFromIndex(self.startIndex.advancedBy(index))
    }
}

display.text = display.text!.substringFromIndex(1)

1

"en_US, fr_CA, es_US" .chopSuffix (5) .chopPrefix (5) // ", fr_CA,"

extension String {
    func chopPrefix(count: Int = 1) -> String {
        return self.substringFromIndex(self.startIndex.advancedBy(count))
    }

    func chopSuffix(count: Int = 1) -> String {
        return self.substringToIndex(self.endIndex.advancedBy(-count))
    }
}

0

स्ट्रिंग से पहला वर्ण हटाने के लिए

let choppedString = String(txtField.text!.characters.dropFirst())

@ जैसनफोगलिया मुझे नहीं पता कि आप वोट देते हैं या नहीं। यदि आप नीचे वोट देते हैं तो क्या आप विस्तार से बता सकते हैं।
हार्दिक ठक्कर

मैंने इसे फिर से जांचा और पाया कि यह सही है। मैंने उत्तर को संपादित किया ताकि मैं इस पर उचित रूप से मतदान कर सकूं।
जेसन फोगलिया

0

यहाँ एक Swift4 दुर्घटना बचाओ संस्करण है chopPrefix, chopSuffixजो समुदाय को छोड़कर ...

extension String {
    func chopPrefix(_ count: Int = 1) -> String {
        return count>self.count ? self : String(self[index(self.startIndex, offsetBy: count)...])
    }
 }

0

Swift3

extension String {
    func chopPrefix(_ count: UInt = 1) -> String {
        return substring(from: characters.index(startIndex, offsetBy: Int(count)))
    }

    func chopSuffix(_ count: UInt = 1) -> String {
        return substring(to: characters.index(endIndex, offsetBy: -Int(count)))
    }
}

class StringChopTests: XCTestCase {
    func testPrefix() {
        XCTAssertEqual("original".chopPrefix(0), "original")
        XCTAssertEqual("Xfile".chopPrefix(), "file")
        XCTAssertEqual("filename.jpg".chopPrefix(4), "name.jpg")
    }

    func testSuffix() {
        XCTAssertEqual("original".chopSuffix(0), "original")
        XCTAssertEqual("fileX".chopSuffix(), "file")
        XCTAssertEqual("filename.jpg".chopSuffix(4), "filename")
    }
}

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