Frage Was ist der kürzeste Weg, um das erste Zeichen aus einer Zeichenfolge in Swift zu entfernen?


Ich möchte das erste Zeichen aus einer Zeichenfolge löschen. Bis jetzt ist das prägnanteste, was ich mir ausgedacht habe:

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

Ich weiß, dass wir nicht mit einer Zeichenfolge in eine Zeichenfolge indexieren können Int wegen Unicode, aber diese Lösung scheint schrecklich ausführlich. Gibt es einen anderen Weg, den ich übersehe?


74
2018-02-11 03:07


Ursprung


Antworten:


Wenn du es benutzt Schnell 3Sie können den zweiten Abschnitt dieser Antwort ignorieren. Eine gute Nachricht ist, dass dies jetzt wieder wirklich prägnant ist! Verwenden Sie einfach die neue remove (at :) -Methode von String.

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

myString // "ello, World"

Ich mag das Globale dropFirst() Funktion dafür.

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

Es ist kurz, klar und funktioniert für alles, was dem Slicable-Protokoll entspricht.

Wenn Sie Swift 2 verwenden, diese Antwort hat sich geändert. Sie können dropFirst weiterhin verwenden, jedoch nicht ohne das erste Zeichen aus Ihren Strings zu löschen characters property und konvertiert das Ergebnis zurück in einen String. DropFirst ist auch eine Methode, keine Funktion geworden.

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

Eine andere Alternative besteht darin, die Suffix-Funktion zu verwenden, um die Strings zu spleißen UTF16View. Natürlich muss dies danach auch wieder in einen String umgewandelt werden.

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

All das bedeutet zu sagen, dass die Lösung, die ich ursprünglich zur Verfügung gestellt habe, sich in neueren Versionen von Swift nicht als die prägnanteste Methode herausgestellt hat. Ich empfehle, auf die Lösung von @chris zurückzugreifen removeAtIndex() wenn Sie nach einer kurzen und intuitiven Lösung suchen.

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

original // ello

Und wie von @ vacawama in den Kommentaren unten angegeben, ist eine andere Option, die den ursprünglichen String nicht ändert, die Verwendung von substringFromIndex.

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

Oder wenn Sie zufällig ein Zeichen am Anfang und am Ende des Strings löschen möchten, können Sie substringWithRange verwenden. Seien Sie sicher, dass Sie sich vor dem Zustand schützen, wenn 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

Die letzte Zeile kann auch in der tiefgestellten Notation geschrieben werden.

let substring = original[newStartIndex..<newEndIndex]

156
2018-02-11 03:31



Update für Swift 4

In Swift 4, String entspricht Collection wieder, so ist es möglich zu verwenden dropFirst und dropLast Trimmen der Anfang und Ende von Streichern. Das Ergebnis ist vom Typ Substring, also musst du das an die String Konstruktor, um zurück zu bekommen String:

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

dropFirst() und dropLast() nimm auch ein Int Geben Sie die Anzahl der zu löschenden Zeichen an:

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

Wenn Sie angeben, dass mehr Zeichen gelöscht werden sollen als in der Zeichenfolge, wird als Ergebnis eine leere Zeichenfolge ("").

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

Update für Swift 3

Wenn Sie nur das erste Zeichen entfernen möchten und die ursprüngliche Zeichenfolge ändern möchten, lesen Sie die Antwort von @ MickMacCallum. Wenn Sie eine neue Zeichenfolge im Prozess erstellen möchten, verwenden Sie substring(from:). Mit einer Erweiterung auf Stringkannst du die Hässlichkeit von verstecken substring(from:) und substring(to:) um nützliche Zusätze zu erstellen, um Anfang und Ende von a zu trimmen 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"

Mögen dropFirst und dropLast vor ihnen werden diese Funktionen abstürzen, wenn nicht genügend Buchstaben in der Zeichenfolge verfügbar sind. Es liegt in der Verantwortung des Anrufers, sie ordnungsgemäß zu verwenden. Dies ist eine gültige Designentscheidung. Man könnte sie schreiben, um ein optionales zurückzugeben, das dann vom Anrufer ausgepackt werden müsste.


Schnell 2.x

Leider in Schnell 2, dropFirst und dropLast (die vorherige beste Lösung) sind nicht so bequem wie zuvor. Mit einer Erweiterung auf Stringkannst du die Hässlichkeit von verstecken substringFromIndex und 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"

Mögen dropFirst und dropLast vor ihnen werden diese Funktionen abstürzen, wenn nicht genügend Buchstaben in der Zeichenfolge verfügbar sind. Es liegt in der Verantwortung des Anrufers, sie ordnungsgemäß zu verwenden. Dies ist eine gültige Designentscheidung. Man könnte sie schreiben, um ein optionales zurückzugeben, das dann vom Anrufer ausgepackt werden müsste.


Im Schnell 1.2, Sie müssen anrufen chopPrefix so was:

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

oder Sie können einen Unterstrich hinzufügen _ zu den Funktionsdefinitionen, um den Parameternamen zu unterdrücken:

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))
    }
}

70
2018-06-14 13:34



Schnell 2.2

'advance' ist nicht verfügbar: Rufen Sie die Methode 'advancedBy (n)' für den Index auf

    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))
    }

Schnelles 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))
    }

Schnell 3.2

Eine Ansicht des Inhalts der Zeichenfolge als eine Sammlung von Zeichen.

@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 ""
}

Schnell 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 ""
    }
}

15
2018-06-14 10:20



In Swift 2:

let cleanedString = String(theString.characters.dropFirst())

ich empfehle https://www.mikeash.com/pyblog/friday-qa-2015-11-06-why-is-swifts-string-api-so-hard.html um Swift-Strings zu verstehen.


12
2017-08-29 12:30



Was ist damit?

s.removeAtIndex(s.startIndex)

Dies setzt natürlich voraus, dass Ihre Zeichenfolge änderbar ist. Es gibt das entfernte Zeichen zurück, ändert jedoch die ursprüngliche Zeichenfolge.


6
2018-02-11 03:15



Ich kenne nichts prägnanteres out of the box, aber Sie könnten einfach Präfix implementieren ++, z.B.,

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

Danach können Sie es nach Herzenslust sehr kurz verwenden:

str.substringFromIndex(++str.startIndex)

1
2018-02-11 03:12



In Swift 2 verwenden Sie diese String-Erweiterung:

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
2017-09-22 14:37



"de_DE, 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))
    }
}

1
2018-06-30 04:15



Die vorherigen Antworten sind ziemlich gut, aber ab heute denke ich, dass dies der prägnanteste Weg ist, das erste Zeichen aus einer Zeichenkette zu entfernen Schnell 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
2018-01-22 19:19



Hängt davon ab, was das Endergebnis sein soll (muting vs nonmutating).

Ab Swift 4.1:

Mutation:

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

Nicht mutierend:

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

Anmerkungen:

  • Ich habe einen zusätzlichen Schritt in die nonmutating Beispiel für Klarheit. Subjektiv wäre die Kombination der letzten beiden Schritte prägnanter.
  • Die Benennung von dropFirst scheint mir etwas komisch, denn wenn ich das verstehe Swift API Design Richtlinien korrekt, dropFirst sollte wirklich etwas wie sein dropingFirst weil es nicht verwirrend ist. Nur ein Gedanke :).

1
2018-05-03 11:05



Swift3

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

    func chopSuffix(_ count: Int = 1) -> String {
        return substring(to: characters.index(endIndex, offsetBy: -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")
    }
}

0
2017-11-29 15:09