Uzyskaj długość ciągu


781

Jak uzyskać długość String? Na przykład mam zmienną zdefiniowaną jak:

var test1: String = "Scott"

Jednak nie mogę znaleźć metody długości na łańcuchu.



Musiałem migrować dużo kodu ręcznie z powodu Swift 3. Więc postanowiłem stworzyć rozszerzenia. Więc teraz, jeśli muszę uaktualnić do nowej głównej wersji, muszę migrować tylko rozszerzenie. Tutaj możesz znaleźć niektóre rozszerzenia Swift 3, które utworzyłem. github.com/tukur187/Swift3
Shkelzen

Odpowiedzi:


1284

Począwszy od Swift 4+

To poprostu:

test1.count

z powodów.

(Dzięki Martin R)

Począwszy od Swift 2:

W Swift 2 Apple zmienił funkcje globalne na rozszerzenia protokołu, rozszerzenia pasujące do dowolnego typu zgodnego z protokołem. Zatem nowa składnia to:

test1.characters.count

(Dzięki JohnDifool za heads-upy)

Od Swift 1

Użyj metody liczenia znaków:

let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
println("unusualMenagerie has \(count(unusualMenagerie)) characters")
// prints "unusualMenagerie has 40 characters"

bezpośrednio z Apple Swift Guide

(Uwaga: w przypadku wersji Swift wcześniejszych niż 1.2 byłoby to countElements(unusualMenagerie)zamiast tego)

dla twojej zmiennej byłoby to

length = count(test1) // was countElements in earlier versions of Swift

Lub możesz użyć test1.utf16count


11
Ciekawe, że countElements to funkcja globalna. Czy istnieje lista funkcji globalnych?
Scott Walter

7
Problem z countElements polega na tym, że deklarowany jest w następujący sposób: func countElements <T> (x: T) -> T.IndexType.DistanceType, a typ zwracany nie akceptuje operacji +.
MarkAurelius

288
Zbyt trudno było dodać metodę str. Long. (podnosi pięść ze złości)
botbot

13
Dzięki Swift 2 mogę to tylko uruchomić: niech len = test1.char Characters.count
Laurent

7
Pamiętaj, że w Swift 4 tak będzie string.count.
Martin R

335

TLDR:

W przypadku Swift 2.0 i 3.0 użyjtest1.characters.count . Ale jest kilka rzeczy, które powinieneś wiedzieć. Więc czytaj dalej.

Liczenie postaci w Swift

Przed wersją Swift 2.0 countbyła funkcją globalną. Począwszy od Swift 2.0, można go wywoływać jako funkcję członka.

test1.characters.count

Zwróci rzeczywistą liczbę znaków Unicode w String, więc jest to najbardziej poprawna alternatywa w tym sensie, że jeśli wydrukujesz ciąg znaków i policzysz znaki ręcznie, uzyskasz ten sam wynik.

Jednak ze względu na sposób Stringsimplementacji w Swift znaki nie zawsze zajmują tyle samo pamięci, więc należy pamiętać, że zachowuje się to zupełnie inaczej niż zwykłe metody liczenia znaków w innych językach.

Na przykład możesz także użyć test1.utf16.count

Ale, jak wskazano poniżej, zwrócona wartość nie jest gwarantowana być taka sama, jak dzwoni countna characters.

Z odniesienia językowego:

Rozszerzone klastry grafemowe mogą składać się z jednego lub więcej skalarów Unicode. Oznacza to, że różne znaki - i różne reprezentacje tego samego znaku - mogą wymagać różnej ilości pamięci do przechowywania. Z tego powodu znaki w Swift nie zajmują tyle samo pamięci w reprezentacji ciągu. W rezultacie liczby znaków w ciągu nie można obliczyć bez iteracji w ciągu w celu ustalenia jego rozszerzonych granic klastra grafemu. Jeśli pracujesz ze szczególnie długimi wartościami łańcucha, pamiętaj, że właściwość znaków musi iterować po skalarach Unicode w całym łańcuchu, aby określić znaki dla tego łańcucha.

Liczba znaków zwróconych przez właściwość character nie zawsze jest taka sama, jak właściwość length NSString zawierającego te same znaki. Długość ciągu NSString jest oparta na liczbie 16-bitowych jednostek kodu w reprezentacji UTF-16 ciągu, a nie na liczbie klastrów rozszerzonych grafem Unicode w ciągu.

Przykładem doskonale ilustrującym sytuację opisaną powyżej jest sprawdzenie długości łańcucha zawierającego pojedynczy znak emoji, jak wskazał n00neimp0rtant w komentarzach.

var emoji = "👍"
emoji.characters.count             //returns 1
emoji.utf16.count                  //returns 2

26
Doceniam twoją szczegółową i ostrożną odpowiedź, ale muszę przyznać, że zaniepokoiło mnie to. Dałeś mi 3 sposoby na uzyskanie długości łańcucha, wszystkie z zastrzeżeniem, że udzielone przez nich odpowiedzi mogą nie być zgodne z oczekiwaniami. Czy naprawdę nie ma wbudowanego w Swift niezawodnego sposobu na uzyskanie dokładnej, niezawodnej wartości długości łańcucha?
n00neimp0rtant

6
@ n00neimp0rtant. Przepraszam, jeśli nie wyjaśniłem. Pierwsze rozwiązanie ( countElements()) pobiera dokładną liczbę znaków w ciągu. Może różnić się od tego, co można uzyskać od wywołania [str length]w Objective-C, ponieważ lengthmetoda zakłada, że ​​wszystkie znaki w ciągu składają się z 16-bitowych jednostek kodu, a countElements()pobiera rzeczywistą liczbę znaków Unicode. Jednak przez większość czasu wszystkie powyższe alternatywy zwrócą te same wyniki, szczególnie jeśli pracujesz ze zwykłymi znakami języka angielskiego.
Cezar

2
@ n00neimp0rtant Ulepszyłem nieco moją odpowiedź, aby była bardziej przejrzysta.
Cezar

2
Rozumiem teraz, co masz na myśli. Właśnie próbowałem uzyskać długość ciągu zawierającego pojedynczy znak Emoji; Cel C dał mi wartość 4, a Swift dał mi wartość 1. Tak więc wydaje się on dokładniejszy (a zatem, jak na ironię, „nie to, czego się spodziewałbym” = P). Dziękuję za wyjaśnienie!
n00neimp0rtant

1
@ n00neimp0rtant Dokładnie! To idealny przykład. Dodam nawet do odpowiedzi
Cezar

92

Aktualizacja Swift 1.2: Nie ma już licznika Elementy do liczenia wielkości kolekcji. Wystarczy użyć funkcji zliczania jako zamiennika: count („Swift”)

Swift 2.0, 3.0 i 3.1:

niech strLength = string.characters.count

Swift 4.2 (od 4.0): [Dokumentacja Apple - Ciągi]

niech strLength = string.count


61

Swift 1.1

extension String {
    var length: Int { return countElements(self) }  // 
}

Swift 1.2

extension String {
    var length: Int { return count(self)         }  // 
}

Swift 2.0

extension String {
    var length: Int { return characters.count    }  // 
}

Szybki 4.2

extension String {
    var length: Int { return self.count }           
}

let str = "Hello"
let count = str.length    // returns 5 (Int)

6
Tak, potrzebujemy warstwy abstrakcji dla składni Swift, która zmienia się co miesiąc!
Cosmin

@Lee To nie działa w szybkim 4., ponieważ znaki są przestarzałe. Bijący się kret nadal trwa. westchnienie
eonista

48

Szybki 4

"string".count

;)

Szybki 3

extension String {
    var length: Int {
        return self.characters.count
    }
}

stosowanie

"string".length


Zwraca String.CharacterView.IndexDistance. Co z Intem?
eonist

@GitSync gdzie? Nie rozumiem cię
Wiaczesław

@Vyacheslav w swift 4 „string” .count zwraca String.CharacterView.IndexDistance Zobacz moją odpowiedź tutaj: stackoverflow.com/a/47203597/5389500, aby dostać się do szybkiego 3 i 4
eonist

Przetestowałem to plac zabaw:
Wiaczesław

//: Playground - noun: a place where people can play import UIKit var str = "Hello, playground" print(type(of: str.characters.count)) print(type(of: str.count))
Wiaczesław

25

Jeśli próbujesz tylko sprawdzić, czy łańcuch jest pusty, czy nie (sprawdzanie długości 0), Swift oferuje prostą metodę testowania logicznego na String

myString.isEmpty

Drugą stroną tej monety były osoby pytające w ObjectiveC, jak zapytać, czy łańcuch jest pusty, a odpowiedzią było sprawdzenie długości 0:

NSString jest pusty


18

tl; dr Jeśli chcesz długość typu String pod względem liczby znaków czytelnych dla człowieka, użyj countElements () . Jeśli chcesz poznać długość w kategoriach liczby rozszerzonych klastrów grafemowych , użyj endIndex . Czytaj dalej, aby poznać szczegóły.

Typ String jest implementowany jako uporządkowana kolekcja (tj. Sekwencja) znaków Unicode i jest zgodny z protokołem CollectionType , który jest zgodny z protokołem _CollectionType , który jest typem wejściowym oczekiwanym przez countElements () . Dlatego countElements () można wywołać, przekazując String typ , i zwróci on liczbę znaków.

Jednak zgodnie z CollectionType , który z kolei jest zgodny z _CollectionType , String implementuje również właściwości obliczeniowe startIndex i endIndex , które faktycznie reprezentują odpowiednio pozycję indeksu przed pierwszym klastrem znaków oraz pozycję indeksu za ostatnim klastrem znaków . Tak więc w łańcuchu „ABC” pozycja indeksu przed A wynosi 0, a po C wynosi 3. Dlatego endIndex = 3, który jest również długością łańcucha.

Tak więc endIndex może być użyty do uzyskania długości dowolnego typu String, prawda?

Cóż, nie zawsze ... Znaki Unicode są w rzeczywistości rozszerzonymi klastrami grafemów , które są sekwencjami jednego lub więcej skalarów Unicode połączonych w celu stworzenia jednej postaci czytelnej dla człowieka.

let circledStar: Character = "\u{2606}\u{20DD}" // ☆⃝

circledStar to pojedyncza postać złożona z U + 2606 (biała gwiazda) i U + 20DD (łączące się koło). Stwórzmy String z circledStar i porównać wyniki countElements () i endIndex .

let circledStarString = "\(circledStar)"
countElements(circledStarString) // 1
circledStarString.endIndex // 2

15

W Swift 2.0 countjuż nie działa. Możesz użyć tego zamiast:

var testString = "Scott"
var length = testString.characters.count

14

Oto coś krótszego i bardziej naturalnego niż użycie funkcji globalnej:

aString.utf16count

Nie wiem jednak, czy jest dostępna w wersji beta 1. Ale na pewno jest w wersji beta 2.


2
Zobacz odpowiedź Cezara. To niekoniecznie da ci liczbę „znaków” w ciągu, dla większości ludzi definicji „znaku”. Z drugiej strony, Cel C również - nie od ciebie zależy, czy ci zależy, czy nie.
jbg

12

Swift 5.1, 5

let flag = "🇵🇷"

print(flag.count)
// Prints "1" --  Counts the characters and emoji as length 1

print(flag.unicodeScalars.count)
// Prints "2" --  Counts the unicode lenght ex. "A" is 65

print(flag.utf16.count)
// Prints "4"

print(flag.utf8.count)
// Prints "8"

11

Zaktualizowano dla Xcode 6 beta 4, zmień metodę utf16count -> utf16Count

 var test1: String = "Scott"
 var length =  test1.utf16Count

Lub

 var test1: String = "Scott"
 var length = test1.lengthOfBytesUsingEncoding(NSUTF16StringEncoding)

Gdy używasz skomplikowanych ciągów znaków z emoji, odpowiedź na utf16countnie będzie błędna
Victor Sigler,

10

Począwszy od wersji Swift 1.2 utf16Countzostał usunięty. Powinieneś teraz użyć count()funkcji globalnej i przekazać widok UTF16 ciągu. Przykład poniżej ...

let string = "Some string"
count(string.utf16)

1
Czy jest wolniejszy niż .utf16count?
samir105

1
Wydaje się, że ta sama prędkość co .utf16count, znacznie szybsza niż liczba (ciąg)
samir105

8

Dla Xcode 7.3 i Swift 2.2.

let str = "🐶"
  1. Jeśli chcesz liczbę znaków wizualnych:

    str.characters.count
  2. Jeśli chcesz mieć „16-bitowe jednostki kodu w reprezentacji UTF-16 ciągu”:

    str.utf16.count

Większość czasu, 1 jest to, czego potrzebujesz.

Kiedy potrzebujesz 2 ? Znalazłem przypadek użycia dla 2 :

let regex = try! NSRegularExpression(pattern:"🐶", 
    options: NSRegularExpressionOptions.UseUnixLineSeparators)
let str = "🐶🐶🐶🐶🐶🐶"
let result = regex.stringByReplacingMatchesInString(str, 
    options: NSMatchingOptions.WithTransparentBounds, 
    range: NSMakeRange(0, str.utf16.count), withTemplate: "dog")
print(result) // dogdogdogdogdogdog

Jeśli użyjesz 1 , wynik jest niepoprawny:

let result = regex.stringByReplacingMatchesInString(str, 
    options: NSMatchingOptions.WithTransparentBounds, 
    range: NSMakeRange(0, str.characters.count), withTemplate: "dog")
print(result) // dogdogdog🐶🐶🐶

7

Możesz spróbować w ten sposób

var test1: String = "Scott"
var length =  test1.bridgeToObjectiveC().length

4
To to samo, cotest1.utf16count
Sulthan

1
@ vladof dobrze, to „rodzaj” działa. Zobacz odpowiedź Cezara.
jbg

6

W Swift 2.x sposób znalezienia długości łańcucha

let findLength = "This is a string of text"
findLength.characters.count

zwraca 24


5

Swift 2.0: Uzyskaj liczbę: yourString.text.characters.count

Zabawnym przykładem tego, jak to jest przydatne, byłoby pokazanie odliczania znaków od pewnej liczby (na przykład 150) w UITextView:

func textViewDidChange(textView: UITextView) {
    yourStringLabel.text = String(150 - yourStringTextView.text.characters.count)
}

4

W swift4 zawsze używałem tego string.countdo dzisiaj

string.endIndex.encodedOffset

jest lepszym podstawieniem, ponieważ jest szybsze - dla 50 000 znaków ciąg znaków jest około 6 razy szybszy niż .count. .countZależy od długości łańcucha, ale .endIndex.encodedOffsettego nie robi.

Ale jest jedno NIE. To nie jest dobre dla ciągów z emoji, da zły wynik, więc tylko.count poprawny.


3

W Swift 4 : Jeśli ciąg nie zawiera znaków Unicode, użyj następujących poleceń

let str : String = "abcd"
let count = str.count // output 4

Jeśli ciąg zawiera znaki Unicode, użyj następujących poleceń:

let spain = "España"
let count1 = spain.count // output 6
let count2 = spain.utf8.count // output 7

Dlaczego miałbyś chcieć użyć utf8.count? To nie daje liczby znaków. Podaje liczbę bajtów potrzebną do kodowania ciągu UTF-8.
rmaddy

2

W Xcode 6.1.1

extension String {    
    var length : Int { return self.utf16Count  }
}

Myślę, że mózgów zmieni to w każdej mniejszej wersji.


2

Uzyskaj wartość ciągu z widoku tekstu lub pola tekstowego:

let textlengthstring = (yourtextview?.text)! as String

Znajdź liczbę znaków w ciągu:

let numberOfChars = textlength.characters.count

2

Oto co skończyłem

let replacementTextAsDecimal = Double(string)

if string.characters.count > 0 &&
    replacementTextAsDecimal == nil &&
    replacementTextHasDecimalSeparator == nil {
        return false
}

Myślę, że próbujesz zrobić coś więcej niż tylko uzyskanie długości łańcucha, a w każdym razie wygląda to na niekompletne (czy nie powinno być też return trueprzypadku?). Czy możesz dokładnie sprawdzić i, w razie potrzeby , edytować swoją odpowiedź? Dziękuję Ci!
Fabio mówi o przywróceniu Moniki

2

Aktualizacja Swift 4 w porównaniu z aktualizacją Swift 3

Swift 4 eliminuje potrzebę stosowania tablicy znaków w String. Oznacza to, że możesz bezpośrednio wywoływać countciąg bez uprzedniego uzyskania tablicy znaków.

"hello".count                  // 5

Podczas gdy w swift 3 będziesz musiał uzyskać tablicę znaków, a następnie policzyć element w tej tablicy. Zauważ, że następująca metoda jest nadal dostępna w swift 4.0, ponieważ nadal możesz wywoływać, charactersaby uzyskać dostęp do tablicy znaków danego ciągu

"hello".characters.count       // 5

Swift 4.0 przyjmuje również Unicode 9 i może teraz interpretować klastry grafemów. Na przykład, liczenie na emoji da ci 1, podczas gdy w szybkim 3.0 możesz otrzymać liczbę większą niż 1.

"👍🏽".count // Swift 4.0 prints 1, Swift 3.0 prints 2
"👨‍❤️‍💋‍👨".count // Swift 4.0 prints 1, Swift 3.0 prints 4

2

Szybki 4

let str =  "Your name"

str.count 

Pamiętaj: spacja również jest liczona


2

Możesz uzyskać długość, pisząc rozszerzenie:

extension String {
    // MARK: Use if it's Swift 2
    func stringLength(str: String) -> Int {
        return str.characters.count
    }

    // MARK: Use if it's Swift 3
    func stringLength(_ str: String) -> Int {
        return str.characters.count
    }

    // MARK: Use if it's Swift 4
    func stringLength(_ str: String) -> Int {
        return str.count
    }
}

1
var str = "Hello, playground"
var newString = str as NSString    

countElements(str)

Zlicza to postacie z Regular Swift String

countElements((newString as String))    

To liczy znaki w NSString


1

Najlepszy sposób na policzenie String w Swift to:

var str = "Hello World"
var length = count(str.utf16)

2
Powinieneś użyć just count (str). Spróbuj użyć licznika (str.utf16) z zaliczką na podciąg ()
Leo Dabus

1

String i NSString to bezpłatny most, dzięki czemu możesz używać wszystkich metod dostępnych dla NSString za pomocą szybkiego ciągu

let x = "test" as NSString
let y : NSString = "string 2"
let lenx = x.count
let leny = y.count

1
test1.characters.count

dostanie liczbę liter / cyfr itp. w ciągu.

dawny:

test1 = "StackOverflow"

print(test1.characters.count)

( drukuje13 ”)


1

Apple odróżniało go od innych głównych języków. Obecny sposób to zadzwonić:

test1.characters.count

Jednak, aby zachować ostrożność, kiedy mówisz o długości, masz na myśli liczbę znaków, a nie liczbę bajtów, ponieważ te dwa mogą być różne, gdy używasz znaków innych niż ascii.

Na przykład; "你好啊hi".characters.countda ci 5, ale to nie jest liczba bajtów. Aby uzyskać rzeczywistą liczbę bajtów, musisz to zrobić "你好啊hi".lengthOfBytes(using: String.Encoding.utf8). To da ci 11.


1

W tej chwili (w Swift 2.3), jeśli używasz:

myString.characters.count 

metoda zwróci typ „Odległość”, jeśli potrzebujesz metody, aby zwrócić liczbę całkowitą, wpisz cast:

var count = myString.characters.count as Int

2
Chodzi Distanceo String.CharacterView to Int , że ta obsada nie powinna być potrzebna.
Martin R
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.