Получить длину строки

780

Как вы получаете длину String ? Например, у меня есть переменная, определенная как:

var test1: String = "Scott"

Тем не менее, я не могу найти метод длины в строке.

Скотт Уолтер
источник
возможный дубликат длины строки в Swift 1.2 и Swift 2.0
King-Wizard
Мне пришлось перенести много кода вручную из-за Swift 3. Поэтому я решил создать расширения. Так что теперь, если придется переходить на новый основной выпуск, мне нужно перенести только расширение. Здесь вы можете найти некоторые расширения Swift 3, которые я создал. github.com/tukur187/Swift3
Шкельзен

Ответы:

1284

Начиная с Swift 4+

Это просто:

test1.count

по причинам.

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

Начиная с Swift 2:

С Swift 2 Apple изменила глобальные функции на расширения протокола, расширения, которые соответствуют любому типу, соответствующему протоколу. Таким образом, новый синтаксис:

test1.characters.count

(Спасибо JohnDifool за советы)

По состоянию на Свифт 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

mginn
источник
11
Интересно, что countElements является глобальной функцией. Есть ли список глобальных функций?
Скотт Уолтер
7
Проблема с countElements состоит в том, что он объявлен так: func countElements <T> (x: T) -> T.IndexType.DistanceType, а возвращаемый тип не принимает операцию +.
Марк Аврелий
288
Было просто слишком сложно добавить метод str.length. (поднимает кулак в гневе)
ботбот
13
С Swift 2 я могу только заставить это работать: let len ​​= test1.characters.count
Laurent
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 в a String, так что это наиболее правильная альтернатива в том смысле, что если вы напечатаете строку и посчитаете символы вручную, вы получите тот же результат.

Однако из-за способа Stringsреализации в Swift символы не всегда занимают одинаковый объем памяти, поэтому имейте в виду, что это ведет себя совершенно иначе, чем обычные методы подсчета символов в других языках.

Например, вы также можете использовать test1.utf16.count

Но, как указано ниже, возвращаемое значение не гарантируется быть такой же , как и вызова countна characters.

Из языковой справки:

Расширенные кластеры графем могут состоять из одного или нескольких скаляров Unicode. Это означает, что различным символам - и различным представлениям одного и того же символа - может потребоваться различное количество памяти для хранения. Из-за этого символы в Swift не занимают одинаковое количество памяти в представлении строки. В результате количество символов в строке не может быть вычислено без итерации по строке для определения границ кластера расширенных графем. Если вы работаете с особенно длинными строковыми значениями, имейте в виду, что свойство символов должно перебирать скаляры Юникода во всей строке, чтобы определить символы для этой строки.

Количество символов, возвращаемых свойством символов, не всегда совпадает со свойством длины строки NSString, содержащей те же символы. Длина строки NSString основана на количестве 16-битных единиц кода в представлении строки UTF-16, а не на количестве кластеров расширенных графем Unicode в строке.

Примером, который отлично иллюстрирует ситуацию, описанную выше, является проверка длины строки, содержащей один символ emoji , как указано в комментариях n00neimp0rtant .

var emoji = "👍"
emoji.characters.count             //returns 1
emoji.utf16.count                  //returns 2
Cezar
источник
26
Я ценю ваш подробный и предостерегающий ответ, но должен признать, что это оставило меня в неловком положении. Вы дали мне 3 способа получить длину строки, все с оговоркой, что ответы, которые они дают, могут не соответствовать вашим ожиданиям. Неужели в Swift нет надежного способа получить точное и надежное значение длины строки?
n00neimp0rtant
6
@ n00neimp0rtant. Извините, если я не дал понять. Первое решение ( countElements()) получает точное количество символов в строке. Это может отличаться от того, что вы получите от вызова [str length]в Objective-C, потому что lengthметод предполагает, что все символы в строке состоят из 16-битных кодовых единиц, в то время как countElements()получает фактическое количество символов Unicode. Однако в большинстве случаев все вышеперечисленные альтернативы будут давать одинаковые результаты, особенно если вы работаете с общими символами английского языка.
Цезарь
2
@ n00neimp0rtant Я немного подправил свой ответ, чтобы сделать его более понятным.
Цезарь
2
Теперь я понимаю, что вы имеете в виду. Я просто попытался получить длину строки, содержащей один символ Emoji; Objective-C дал мне значение 4, а Swift дал мне значение 1. Так что на самом деле это кажется более точным (и поэтому, по иронии судьбы, «не то, что я ожидал» = P). Благодарю за разъяснение!
n00neimp0rtant
1
@ n00neimp0rtant Точно! Это прекрасный пример. Я даже добавлю это к ответу
Цезарь
92

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

Swift 2.0, 3.0 и 3.1:

let strLength = string.characters.count

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

let 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    }  // 
}

Swift 4.2

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

let str = "Hello"
let count = str.length    // returns 5 (Int)
whitneyland
источник
6
Да, нам нужен слой абстракции для синтаксиса Swift, который меняется ежемесячно!
Космин
@ Ли Это не работает в Swift 4., поскольку символы устарели. Бегущий по кругу гонщик продолжается. вздох
эонист
48

Swift 4

"string".count

;)

Свифт 3

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

Применение

"string".length

Вячеслав
источник
Возвращает String.CharacterView.IndexDistance. А как насчет Int?
eonist
@ GitSync где? Я не понимаю тебя
Вячеслав
@Vyacheslav in swift 4 "string" .count возвращает String.CharacterView.IndexDistance Смотрите мой ответ здесь: stackoverflow.com/a/47203597/5389500, чтобы получить int в swift 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 может быть использован для получения длины любого типа String, верно?

Ну, не всегда ... Символы 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
Antoine
источник
14

Вот что-то более короткое и более естественное, чем использование глобальной функции:

aString.utf16count

Я не знаю, доступен ли он в бета-версии 1, хотя. Но это определенно есть в бета-версии 2.

Жан Ле Муаньян
источник
2
Смотрите ответ Цезаря. Это не обязательно даст вам количество «символов» в строке, для большинства людей определение «символ». С другой стороны, и Objective-C - и вам решать, волнует ли вас это или нет.
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"
Saranjith
источник
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, намного быстрее, чем count (строка)
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
Sulthan
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)
}
CJD
источник
4

В swift4 я всегда использовал string.countдо сегодняшнего дня, я обнаружил, что

string.endIndex.encodedOffset

это лучшая замена, потому что она быстрее - для 50 000 символов строка примерно в 6 раз быстрее, чем .count. .countЗависит от длины строки , но .endIndex.encodedOffsetне делает.

Но есть один НЕТ. Это не хорошо для струн с смайликами, это даст неправильный результат, поэтому только .countправильно.

VYT
источник
3

В Swift 4 : если строка не содержит символов Юникода, используйте следующее

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

Если строка содержит символы Юникода, используйте следующее:

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 изменит это на каждой минорной версии.

user3812138
источник
2

Получите строковое значение из вашего текстового представления или текстового поля:

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

Найдите количество символов в строке:

let numberOfChars = textlength.characters.count
kalyan711987
источник
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 устраняет необходимость в массиве символов в строке. Это означает, что вы можете напрямую вызывать countстроку без предварительного получения массива символов.

"hello".count                  // 5

В то время как в Swift 3 вам нужно будет получить массив символов, а затем посчитать элемент в этом массиве. Обратите внимание, что этот следующий метод все еще доступен в swift 4.0, так как вы все равно можете вызвать charactersмассив символов данной строки

"hello".characters.count       // 5

Swift 4.0 также принимает Unicode 9 и теперь может интерпретировать кластеры графем. Например, если рассчитывать на смайликов, вы получите 1, а в Swift 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
Fangming
источник
2

Swift 4

let str =  "Your name"

str.count 

Помните: пробел также учитывается в числе

Mr.Shin
источник
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)

Это считает символы в регулярной быстрой строке

countElements((newString as String))    

Это подсчитывает символы в строке NSString

brokenrhino
источник
1

Лучший способ посчитать String в Swift это:

var str = "Hello World"
var length = count(str.utf16)
Zaldy
источник
2
Вы должны использовать просто считать (ул). Попробуйте использовать счетчик (str.utf16) с подстрокой advance ()
Лео Дабус
1

String и NSString являются бесплатным мостом, поэтому вы можете использовать все методы, доступные для NSString, с помощью swift String.

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 

метод вернет тип «Distance», если вам нужен метод для возврата Integer, вы должны набрать приведение следующим образом:

var count = myString.characters.count as Int
Джесси
источник
2
DistanceИз String.CharacterView это Int , не должно быть никакой необходимости в этом броске.
Мартин Р