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
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
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”)
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:
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
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"
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 ...
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 ="🐶"
Jeśli chcesz liczbę znaków wizualnych:
str.characters.count
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🐶🐶🐶
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.
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 //Swift4.0 prints 1,Swift3.0 prints 4
extensionString{// 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
}}
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.
Odpowiedzi:
Począwszy od Swift 4+
To poprostu:
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:
(Dzięki JohnDifool za heads-upy)
Od Swift 1
Użyj metody liczenia znaków:
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
Lub możesz użyć test1.utf16count
źródło
string.count
.TLDR:
W przypadku Swift 2.0 i 3.0 użyj
test1.characters.count
. Ale jest kilka rzeczy, które powinieneś wiedzieć. Więc czytaj dalej.Liczenie postaci w Swift
Przed wersją Swift 2.0
count
była funkcją globalną. Począwszy od Swift 2.0, można go wywoływać jako funkcję członka.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
Strings
implementacji 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
count
nacharacters
.Z odniesienia językowego:
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.
źródło
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żlength
metoda zakłada, że wszystkie znaki w ciągu składają się z 16-bitowych jednostek kodu, acountElements()
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.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:Swift 4.2 (od 4.0): [Dokumentacja Apple - Ciągi]
źródło
Swift 1.1
Swift 1.2
Swift 2.0
Szybki 4.2
źródło
Szybki 4
"string".count
;)
Szybki 3
stosowanie
"string".length
źródło
//: 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))
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
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
źródło
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.
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 .
źródło
W Swift 2.0
count
już nie działa. Możesz użyć tego zamiast:źródło
Oto coś krótszego i bardziej naturalnego niż użycie funkcji globalnej:
Nie wiem jednak, czy jest dostępna w wersji beta 1. Ale na pewno jest w wersji beta 2.
źródło
Swift 5.1, 5
źródło
Zaktualizowano dla Xcode 6 beta 4, zmień metodę utf16count -> utf16Count
Lub
źródło
utf16count
nie będzie błędnaPocząwszy od wersji Swift 1.2
utf16Count
został usunięty. Powinieneś teraz użyćcount()
funkcji globalnej i przekazać widok UTF16 ciągu. Przykład poniżej ...źródło
Dla Xcode 7.3 i Swift 2.2.
Jeśli chcesz liczbę znaków wizualnych:
Jeśli chcesz mieć „16-bitowe jednostki kodu w reprezentacji UTF-16 ciągu”:
Większość czasu, 1 jest to, czego potrzebujesz.
Kiedy potrzebujesz 2 ? Znalazłem przypadek użycia dla 2 :
Jeśli użyjesz 1 , wynik jest niepoprawny:
źródło
Możesz spróbować w ten sposób
źródło
test1.utf16count
W Swift 2.x sposób znalezienia długości łańcucha
zwraca 24
źródło
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:
źródło
W swift4 zawsze używałem tego
string.count
do dzisiajjest lepszym podstawieniem, ponieważ jest szybsze - dla 50 000 znaków ciąg znaków jest około 6 razy szybszy niż
.count
..count
Zależy od długości łańcucha, ale.endIndex.encodedOffset
tego 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.źródło
W Swift 4 : Jeśli ciąg nie zawiera znaków Unicode, użyj następujących poleceń
Jeśli ciąg zawiera znaki Unicode, użyj następujących poleceń:
źródło
utf8.count
? To nie daje liczby znaków. Podaje liczbę bajtów potrzebną do kodowania ciągu UTF-8.W Xcode 6.1.1
Myślę, że mózgów zmieni to w każdej mniejszej wersji.
źródło
Uzyskaj wartość ciągu z widoku tekstu lub pola tekstowego:
Znajdź liczbę znaków w ciągu:
źródło
Oto co skończyłem
źródło
return true
przypadku?). Czy możesz dokładnie sprawdzić i, w razie potrzeby , edytować swoją odpowiedź? Dziękuję Ci!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ć
count
ciąg bez uprzedniego uzyskania tablicy znaków.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ć,
characters
aby uzyskać dostęp do tablicy znaków danego ciąguSwift 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.
źródło
Szybki 4
Pamiętaj: spacja również jest liczona
źródło
Możesz uzyskać długość, pisząc rozszerzenie:
źródło
Zlicza to postacie z Regular Swift String
To liczy znaki w NSString
źródło
Najlepszy sposób na policzenie String w Swift to:
źródło
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
źródło
dostanie liczbę liter / cyfr itp. w ciągu.
dawny:
( drukuje „ 13 ”)
źródło
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.count
da 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.źródło
W tej chwili (w Swift 2.3), jeśli używasz:
metoda zwróci typ „Odległość”, jeśli potrzebujesz metody, aby zwrócić liczbę całkowitą, wpisz cast:
źródło
Distance
oString.CharacterView
toInt
, że ta obsada nie powinna być potrzebna.