Отримайте довжину рядка


781

Як ви отримуєте довжину String? Наприклад, у мене є змінна, визначена як:

var test1: String = "Scott"

Однак я не можу знайти метод довжини на рядку.



Мені довелося мігрувати багато коду вручну через Swift 3. Тому я вирішив створити розширення. Отже, якщо доведеться оновити до нового основного випуску, мені потрібно перенести лише розширення. Тут ви можете знайти кілька створених мною розширень Swift 3. github.com/tukur187/Swift3
Shkelzen

Відповіді:


1284

Станом на Swift 4+

Це просто:

test1.count

з причин.

(Спасибі Мартіну Р.)

Станом на Swift 2:

З Swift 2 Apple змінила глобальні функції на розширення протоколу, розширення, які відповідають будь-якому типу, що відповідає протоколу. Таким чином, новий синтаксис:

test1.characters.count

(Дякую JohnDifool за голову вгору)

Станом на Swift 1

Використовуйте метод підрахунку символів:

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

прямо з посібника Apple Swift

(зауважте, для версій Swift раніше, ніж 1.2, це буде countElements(unusualMenagerie)замість цього)

для вашої змінної, це було б

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

Або ви можете використовувати test1.utf16count


11
Цікаво, що countElements - це глобальна функція. Чи є список глобальних функцій?
Скотт Уолтер

7
Проблема з countElements полягає в тому, що вона оголошена так: func countElements <T> (x: T) -> T.IndexType.DistanceType і тип повернення не приймає операцію +.
МаркАврелій

288
Просто було важко додати метод str.length. (в гніві піднімає кулак)
бот

13
За допомогою Swift 2 я можу лише працювати на цьому: хай len = test1.characters.count
Лоран

7
Зауважте, що з Swift 4 так і буде string.count.
Мартін Р.

335

TLDR:

Для Swift 2.0 та 3.0 використовуйте test1.characters.count. Але, ви повинні знати кілька речей. Отже, читайте далі.

Підрахунок символів у Swift

До Swift 2.0 countбула глобальною функцією. Що стосується Swift 2.0, його можна назвати функцією члена.

test1.characters.count

Він поверне фактичну кількість символів Unicode в String, так що це найбільш правильна альтернатива в тому сенсі, що, якщо ви надрукували рядок і порахували символи вручну, ви отримали б той самий результат.

Однак через те, як Stringsреалізовано в Swift, символи не завжди займають однаковий об'єм пам'яті, тому майте на увазі, що це поводиться зовсім інакше, ніж звичайні методи підрахунку символів в інших мовах.

Наприклад, ви також можете використовувати test1.utf16.count

Але, як зазначено нижче, повертається значення не гарантовано бути такою ж , як і виклику countна characters.

З мовної довідки:

Розширені кластери графеми можуть складатися з одного або декількох скалярів Unicode. Це означає, що різні символи - і різні зображення одного і того ж символу - можуть вимагати різного обсягу пам'яті для зберігання. Через це символи Swift не займають однаковий об'єм пам'яті в рамках представлення рядка. В результаті кількість символів у рядку не може бути обчислена без ітерації через рядок для визначення її розширених меж кластеру графем. Якщо ви працюєте з особливо довгими рядковими значеннями, майте на увазі, що властивість символів повинна повторюватися над скалярами Unicode у всій рядку, щоб визначити символи для цього рядка.

Кількість символів, повернених властивістю символів, не завжди збігається з властивістю довжини NSString, що містить ті самі символи. Довжина NSString заснована на кількості 16-бітових кодових одиниць у представленні UTF-16 рядка, а не на кількості розширених кластерних графем Unicode всередині рядка.

Приклад, який ідеально ілюструє описану вище ситуацію, - це перевірка довжини рядка, що містить єдиний символ емоджи, на що вказує n00neimp0rtant у коментарях.

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

26
Я ціную вашу детальну і обережну відповідь, але мушу визнати, що вона залишила мене непросто. Ви дали мені 3 способи отримати довжину рядка, все з відмовою в тому, що відповіді, які вони дають, можуть бути не такими, яких ви очікуєте. Чи справді немає вбудованого надійного способу в Swift отримати точне, надійне значення довжини струни?
n00neimp0rtant

6
@ n00neimp0rtant. Вибачте, якщо я не дав зрозуміти. Перше рішення ( countElements()) отримує точну кількість символів у рядку. Це може відрізнятися від того, що ви отримаєте від виклику [str length]в Objective-C, оскільки lengthметод передбачає, що всі символи в рядку складаються з 16-бітних одиниць коду, при цьому countElements()отримується фактична кількість символів Unicode. Однак більшу частину часу всі вищезазначені альтернативи повертають однакові результати, особливо якщо ви працюєте з загальними символами англійської мови.
Цезар

2
@ n00neimp0rtant Я трохи змінив свою відповідь, щоб спробувати зробити її більш зрозумілою.
Цезар

2
Я бачу, що ти маєш на увазі зараз. Я просто спробував отримати довжину рядка, що містить один символ Emoji; Objective-C дав мені значення 4, а Свіфт дав мені значення 1. Отже, це насправді здається більш точним (і, отже, іронічно "не те, що я очікував" = P). Дякуємо за роз’яснення!
n00neimp0rtant

1
@ n00neimp0rtant Рівно! Це ідеальний приклад. Я навіть додам це у відповідь
Цезар

92

Swift 1.2 Оновлення: більше немає countElements для підрахунку розміру колекцій. Просто використовуйте функцію підрахунку як заміну: count ("Swift")

Swift 2.0, 3.0 та 3.1:

нехай strLength = string.characters.count

Swift 4.2 (4.0 далі): [Документація Apple - Струни]

нехай strLength = string.count


61

Швидкий 1.1

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

Швидкий 1.2

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

Швидкий 2.0

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

Швидкий 4.2

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

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

6
Так, нам потрібен шар абстракції для синтаксису Свіфта, який змінюється щомісяця!
Космін

@Lee Це не працює в швидкості 4. оскільки символи застаріли. Пробіг по молюсків-каламбурів продовжується. зітхання
еоніст

48

Швидкий 4

"string".count

;)

Швидкий 3

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

використання

"string".length


Він повертає String.CharacterView.IndexDistance. Що про Інт?
еоніст

@GitSync де? Я вас не розумію
В’ячеслав

@Vyacheslav in swift 4 "string" .count return String.CharacterView.IndexDistance Дивіться мою відповідь тут: stackoverflow.com/a/47203597/5389500, щоб отримати int у швидких 3 та 4
eonist

Я перевірив, що це майданчик:
В’ячеслав

//: 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))
В’ячеслав

25

Якщо ви просто намагаєтесь побачити, чи рядок порожній чи ні (перевірка довжини 0), Swift пропонує простий булевий метод тестування на String

myString.isEmpty

Іншою стороною цієї монети були люди, які запитували в ObjectiveC, як запитати, чи рядок порожній, де відповідь повинна перевіряти на довжину 0:

NSString порожній


18

tl; dr Якщо вам потрібна довжина типу String з точки зору кількості символів, прочитаних людиною, використовуйте countElements () . Якщо ви хочете знати довжину з точки зору кількості розширених кластерів графем , використовуйте endIndex . Детальніше читайте далі.

Тип String реалізований як упорядкована колекція (тобто послідовність) символів Unicode, і вона відповідає протоколу CollectionType , який відповідає протоколу _CollectionType , який є типом введення, очікуваним countElements () . Тому countElements () можна викликати, передаючи тип String , і він поверне кількість символів.

Однак, відповідно до CollectionType , який, у свою чергу, відповідає _CollectionType , String також реалізує обчислювані властивості startIndex та endIndex , які фактично представляють позицію індексу перед першим кластерним символом та позицію індексу після останнього кластера символів відповідно . Так, у рядку "ABC" позиція індексу перед A дорівнює 0, а після C - 3. Отже, endIndex = 3, яка також є довжиною рядка.

Отже, endIndex можна використовувати для отримання довжини будь-якого типу рядка, значить, правда?

Ну, не завжди ... Символи Unicode - це фактично розширені кластери графем , що є послідовностями одного або декількох скалярів Unicode, об'єднаних для створення єдиного людського читаного символу.

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

circledStar - це єдиний символ, що складається з U + 2606 (біла зірка) та U + 20DD (поєднуюче коло, що поєднує). Створимо String з CircledStar та порівняємо результати countElements () та endIndex .

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

15

У Swift 2.0 countвже не працює. Ви можете використовувати це замість:

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

14

Ось щось коротше і природніше, ніж використання глобальної функції:

aString.utf16count

Я не знаю, чи доступний він у бета-версії 1. Але це точно в бета-2.


2
Дивіться відповідь Цезаря. Це не обов'язково дасть вам кількість символів у рядку, для більшості людей визначення "символу". Знову ж таки, ні Objective-C - вирішувати, турбуєтесь ви чи ні.
jbg

12

Швидкий 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

Оновлено для Xcode 6 beta 4, змінити метод utf16count -> utf16Count

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

Або

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

Коли ви використовуєте складні рядки з смайлами, відповідь з utf16countбуде помилковою
Віктор Зіґлер

10

Станом на Swift 1.2 utf16Countбуло видалено. Тепер вам слід використовувати глобальну count()функцію та передати UTF16 подання рядка. Приклад нижче ...

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

1
Це повільніше, ніж .utf16count?
samir105

1
Здається, така ж швидкість, як .utf16count, набагато швидша, ніж підрахунок (рядок)
samir105

8

Для Xcode 7.3 та Swift 2.2.

let str = "🐶"
  1. Якщо ви хочете кількість візуальних символів:

    str.characters.count
  2. Якщо ви хочете, щоб "16-бітні одиниці коду в представленні UTF-16 рядка":

    str.utf16.count

Більшість часу 1 - це те, що вам потрібно.

Коли вам знадобиться 2 ? Я знайшов випадок використання для 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

Якщо ви використовуєте 1 , результат неправильний:

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

7

Ви можете спробувати так

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

4
Це те саме, щоtest1.utf16count
Султан

1
@vladof добре, це "вид" працює. Дивіться відповідь Цезаря.
jbg

6

у Swift 2.x наведено нижче, як знайти довжину рядка

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

повертає 24


5

Swift 2.0: Отримайте рахунок: yourString.text.characters.count

Прикольним прикладом того, як це корисно, буде показати зворотний відлік символів від деякого числа (наприклад, 150) у UITextView:

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

4

У swift4 я завжди використовував string.countдо сьогоднішнього дня

string.endIndex.encodedOffset

є кращою заміною, оскільки вона швидша - для 50 000 символів рядок приблизно в 6 разів швидше, ніж .count. .countЗалежить від довжини рядка , але .endIndex.encodedOffsetне робить.

Але є один НІ. Це не добре для рядків з емоджи, це дасть неправильний результат, тому лише .countправильно.


3

У Swift 4 : Якщо рядок не містить символів unicode, використовуйте наступне

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

Якщо рядок містить символи unicode, використовуйте наступне:

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

Навіщо ви хочете використовувати utf8.count? Це не дає кількість символів. Він дає кількість байтів, необхідних для кодування UTF-8 рядка.
rmaddy

2

У Xcode 6.1.1

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

Я думаю, що brainiacs змінить це на кожній незначній версії.


2

Отримайте значення рядка з свого перегляду тексту чи текстового поля:

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

Знайдіть кількість символів у рядку:

let numberOfChars = textlength.characters.count

2

Ось що я закінчив робити

let replacementTextAsDecimal = Double(string)

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

Я думаю, ви намагаєтеся зробити більше, ніж просто отримати довжину рядка, і в будь-якому випадку це виглядає неповно (не повинно бути також return true справи?). Чи можете ви перевірити ще раз і, на випадок, відредагувати свою відповідь? Дякую!
Фабіо каже: Відновити Моніку

2

Оновлення Swift 4 порівняно з Swift 3

Swift 4 усуває потребу в масиві символів на String. Це означає, що ви можете безпосередньо дзвонити countпо рядку, не отримуючи попередньо масив символів.

"hello".count                  // 5

Тоді як у швидкому 3 вам доведеться отримати масив символів, а потім порахувати елемент у цьому масиві. Зауважте, що наступний метод все ще доступний у швидкій версії 4.0, оскільки ви все ще можете зателефонувати, charactersщоб отримати доступ до масиву символів даної рядки

"hello".characters.count       // 5

Swift 4.0 також приймає Unicode 9 і тепер він може інтерпретувати кластери графеми. Наприклад, якщо порахувати емоджи, ви отримаєте 1 при швидкій версії 3.0, ви можете отримати кількість, більша за 1.

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

2

Швидкий 4

let str =  "Your name"

str.count 

Пам'ятайте: пробіл також зараховується до числа


2

Ви можете отримати довжину, просто написавши розширення:

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)

Це враховує символів у Regular Swift String

countElements((newString as String))    

Це рахує символів у NSString


1

Найкращий спосіб порахувати рядок у Swift:

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

2
Вам слід використовувати просто count (str). Спробуйте tu use count (str.utf16) з підрядком вперед ()
Лео Дабус

1

String і NSString - це безкоштовний міст, тому ви можете використовувати всі доступні методи NSString за допомогою швидкого рядка

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

1
test1.characters.count

отримає вам кількість букв / цифр тощо у вашому рядку.

колишній:

test1 = "StackOverflow"

print(test1.characters.count)

( друкує " 13 ")


1

Apple відрізняла його від інших основних мов. Поточний спосіб - зателефонувати:

test1.characters.count

Однак будьте обережні, коли ви говорите довжину, ви маєте на увазі кількість символів, а не кількість байтів, тому що ці два можуть бути різними, коли ви використовуєте символи, які не належать ascii.

Наприклад; "你好啊hi".characters.countдасть вам 5, але це не кількість байтів. Щоб отримати реальну кількість байтів, вам потрібно зробити "你好啊hi".lengthOfBytes(using: String.Encoding.utf8). Це дасть вам 11.


1

Зараз (у Swift 2.3), якщо ви використовуєте:

myString.characters.count 

метод поверне тип "Відстань", якщо вам потрібен метод для повернення Integer, слід ввести ролик таким чином:

var count = myString.characters.count as Int

2
DistanceЗ String.CharacterView це Int , не повинно бути ніякої необхідності в цьому кидку.
Мартін Р
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.