Obtener la longitud de una cadena

780

¿Cómo se obtiene la longitud de un String? Por ejemplo, tengo una variable definida como:

var test1: String = "Scott"

Sin embargo, parece que no puedo encontrar un método de longitud en la cadena.

Scott Walter
fuente
posible duplicado de la longitud
King-Wizard
Tuve que migrar mucho código manualmente debido a Swift 3. Así que decidí crear extensiones. Entonces, si tengo que actualizar a una nueva versión principal, solo necesito migrar la extensión. Aquí puedes encontrar algunas extensiones de Swift 3 que he creado. github.com/tukur187/Swift3
Shkelzen

Respuestas:

1284

A partir de Swift 4+

Es solo:

test1.count

por razones.

(Gracias a Martin R)

A partir de Swift 2:

Con Swift 2, Apple ha cambiado las funciones globales a extensiones de protocolo, extensiones que coinciden con cualquier tipo conforme a un protocolo. Así, la nueva sintaxis es:

test1.characters.count

(Gracias a JohnDifool por el aviso)

A partir de Swift 1

Use el método de recuento de caracteres:

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

directamente de la Guía Apple Swift

(nota, para versiones de Swift anteriores a 1.2, esto sería en su countElements(unusualMenagerie)lugar)

para su variable, sería

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

O puede usar test1.utf16count

mginn
fuente
11
Es interesante que countElements sea una función global. ¿Hay una lista de funciones globales?
Scott Walter
77
El problema con countElements es que se declara así: func countElements <T> (x: T) -> T.IndexType.DistanceType y el tipo de retorno no acepta la operación +.
MarkAurelius
288
Era demasiado difícil agregar un método str.length. (levanta el puño con ira)
botbot
13
Con Swift 2, solo puedo hacer que esto funcione: let len ​​= test1.characters.count
Laurent
77
Tenga en cuenta que con Swift 4, lo será string.count.
Martin R
335

TLDR:

Para Swift 2.0 y 3.0, use test1.characters.count. Pero, hay algunas cosas que debes saber. Entonces, sigue leyendo.

Contando personajes en Swift

Antes de Swift 2.0, countera una función global. A partir de Swift 2.0, se puede llamar como una función miembro.

test1.characters.count

Devolverá el número real de caracteres Unicode en a String, por lo que es la alternativa más correcta en el sentido de que, si imprime la cadena y cuenta los caracteres a mano, obtendrá el mismo resultado.

Sin embargo, debido a la forma en que Stringsse implementan en Swift, los caracteres no siempre ocupan la misma cantidad de memoria, así que tenga en cuenta que esto se comporta de manera bastante diferente a los métodos habituales de conteo de caracteres en otros idiomas.

Por ejemplo, también puedes usar test1.utf16.count

Pero, como se señala más adelante, el valor devuelto no se garantiza que sea la misma que la de llamar counta characters.

De la referencia del idioma:

Los grupos de grafemas extendidos pueden estar compuestos por uno o más escalares Unicode. Esto significa que diferentes caracteres, y diferentes representaciones del mismo carácter, pueden requerir diferentes cantidades de memoria para almacenar. Debido a esto, los personajes en Swift no ocupan la misma cantidad de memoria dentro de la representación de una cadena. Como resultado, el número de caracteres en una cadena no se puede calcular sin iterar a través de la cadena para determinar los límites del grupo de grafemas extendido. Si está trabajando con valores de cadena particularmente largos, tenga en cuenta que la propiedad de caracteres debe iterar sobre los escalares Unicode en toda la cadena para determinar los caracteres para esa cadena.

El recuento de los caracteres devueltos por la propiedad de caracteres no siempre es el mismo que la propiedad de longitud de un NSString que contiene los mismos caracteres. La longitud de un NSString se basa en la cantidad de unidades de código de 16 bits dentro de la representación UTF-16 de la cadena y no en la cantidad de clústeres de grafemas extendidos Unicode dentro de la cadena.

Un ejemplo que ilustra perfectamente la situación descrita anteriormente es la de verificar la longitud de una cadena que contiene un solo carácter emoji, como lo señala n00neimp0rtant en los comentarios.

var emoji = "👍"
emoji.characters.count             //returns 1
emoji.utf16.count                  //returns 2
Cezar
fuente
26
Agradezco su detallada y cautelosa respuesta, pero debo admitir que me ha dejado incómodo. Me diste 3 formas de obtener la longitud de una cadena, todo con el descargo de responsabilidad de que las respuestas que dan podrían no ser lo que esperas. ¿Realmente no hay una forma confiable integrada en Swift para obtener un valor de longitud preciso y confiable de una cadena?
n00neimp0rtant
66
@ n00neimp0rtant. Lo siento si no lo dejé claro. La primera solución ( countElements()) obtiene el número exacto de caracteres en la cadena. Puede ser diferente de lo que obtendría al llamar [str length]en Objective-C, porque el lengthmétodo supone que todos los caracteres de la cadena están compuestos por unidades de código de 16 bits, mientras que countElements()obtiene el número real de caracteres Unicode. Sin embargo, la mayoría de las veces todas las alternativas anteriores arrojarán los mismos resultados, especialmente si está trabajando con caracteres comunes en inglés.
Cezar
2
@ n00neimp0rtant Modifiqué un poco mi respuesta para intentar aclararlo.
Cezar
2
Ahora entiendo lo que quieres decir. Acabo de intentar obtener la longitud de una cadena que contiene un solo personaje Emoji; Objective-C me dio un valor de 4, y Swift me dio un valor de 1. Por lo tanto, en realidad parece más preciso (y por lo tanto, irónicamente "no es lo que esperaría" = P). ¡Gracias por la aclaración!
n00neimp0rtant
1
@ n00neimp0rtant ¡Exactamente! Ese es un ejemplo perfecto. Incluso lo agregaré a la respuesta
Cezar
92

Actualización de Swift 1.2: ya no hay un countElements para contar el tamaño de las colecciones. Simplemente use la función de conteo como reemplazo: count ("Swift")

Swift 2.0, 3.0 y 3.1:

deje strLength = string.characters.count

Swift 4.2 (4.0 en adelante): [Documentación de Apple - Cadenas]

deje strLength = string.count

San
fuente
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
fuente
66
¡Sí, necesitamos una capa de abstracción para la sintaxis de Swift que cambia mensualmente!
Cosmin
@Lee Esto no funciona en 4. rápido ya que los caracteres están en desuso. La carrera de whac-a-mole continúa. suspiro
eonista
48

Swift 4

"string".count

;)

Swift 3

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

uso

"string".length

Vyacheslav
fuente
Devuelve String.CharacterView.IndexDistance. ¿Qué hay de Int?
eonista el
@GitSync donde? No te entiendo
Vyacheslav
@Vyacheslav en swift 4 "string" .count devuelve String.CharacterView.IndexDistance Vea mi respuesta aquí: stackoverflow.com/a/47203597/5389500 para obtener int en swift 3 y 4
eonista
He probado este es el patio de recreo:
Vyacheslav
//: 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))
Vyacheslav
25

Si solo está tratando de ver si una cadena está vacía o no (verificando la longitud de 0), Swift ofrece un método de prueba booleano simple en String

myString.isEmpty

El otro lado de esta moneda era la gente que preguntaba en ObjectiveC cómo preguntar si una cadena estaba vacía donde la respuesta era verificar una longitud de 0:

NSString está vacío

Kendall Helmstetter Gelner
fuente
18

tl; dr Si desea la longitud de un tipo de cadena en términos de la cantidad de caracteres legibles por humanos, use countElements () . Si desea conocer la longitud en términos de la cantidad de grupos de grafemas extendidos , use endIndex . Sigue leyendo para más detalles.

El tipo de cadena se implementa como una colección ordenada (es decir, secuencia) de caracteres Unicode, y se ajusta al protocolo CollectionType , que se ajusta al protocolo _CollectionType , que es el tipo de entrada esperado por countElements () . Por lo tanto, se puede llamar a countElements () , pasando un tipo de cadena , y devolverá el recuento de caracteres.

Sin embargo, al conformarse con CollectionType , que a su vez se ajusta a _CollectionType , String también implementa las propiedades calculadas startIndex y endIndex , que realmente representan la posición del índice antes del primer grupo de caracteres y la posición del índice después del último grupo de caracteres, respectivamente . Entonces, en la cadena "ABC", la posición del índice antes de A es 0 y después de C es 3. Por lo tanto, endIndex = 3, que también es la longitud de la cadena.

Entonces, endIndex se puede usar para obtener la longitud de cualquier tipo de cadena, entonces, ¿verdad?

Bueno, no siempre ... Los personajes Unicode en realidad son grupos de grafemas extendidos , que son secuencias de uno o más escalares Unicode combinados para crear un solo personaje legible por humanos.

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

circledStar es un único personaje formado por U + 2606 (una estrella blanca) y U + 20DD (un círculo de combinación). Creemos una Cadena desde circledStar y comparemos los resultados de countElements () y endIndex .

let circledStarString = "\(circledStar)"
countElements(circledStarString) // 1
circledStarString.endIndex // 2
Scott Gardner
fuente
15

En Swift 2.0 countya no funciona. Puedes usar esto en su lugar:

var testString = "Scott"
var length = testString.characters.count
Antoine
fuente
14

Aquí hay algo más corto y más natural que usar una función global:

aString.utf16count

Sin embargo, no sé si está disponible en beta 1. Pero definitivamente está ahí en beta 2.

Jean Le Moignan
fuente
2
Ver la respuesta de Cezar. Esto no necesariamente le dará el número de "caracteres" en la cadena, para la definición de "carácter" de la mayoría de las personas. Por otra parte, tampoco lo hizo Objective-C: depende de usted decidir si le importa o no.
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
fuente
11

Actualizado para Xcode 6 beta 4, método de cambio utf16count -> utf16Count

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

O

 var test1: String = "Scott"
 var length = test1.lengthOfBytesUsingEncoding(NSUTF16StringEncoding)
Kiet Nguyen
fuente
Cuando usas cadenas complejas con emoji, la respuesta utf16countserá incorrecta
Victor Sigler
10

A partir de Swift 1.2 utf16Countse ha eliminado. Ahora debe usar la count()función global y pasar la vista UTF16 de la cadena. Ejemplo a continuación ...

let string = "Some string"
count(string.utf16)
Jeremy Fox
fuente
1
¿Es más lento que .utf16count?
samir105
1
Parece la misma velocidad que .utf16count, mucho más rápido que el conteo (string)
samir105
8

Para Xcode 7.3 y Swift 2.2.

let str = "🐶"
  1. Si quieres la cantidad de caracteres visuales:

    str.characters.count
  2. Si desea las "unidades de código de 16 bits dentro de la representación UTF-16 de la cadena":

    str.utf16.count

La mayoría de las veces, 1 es lo que necesitas.

¿Cuándo necesitarías 2 ? He encontrado un caso de uso para 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

Si usa 1 , el resultado es incorrecto:

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

Podrías intentar así

var test1: String = "Scott"
var length =  test1.bridgeToObjectiveC().length
Anil Varghese
fuente
44
Es lo mismo quetest1.utf16count
Sulthan
1
@vladof bueno, "tipo de" funciona. Ver la respuesta de Cezar.
jbg
6

en Swift 2.x lo siguiente es cómo encontrar la longitud de una cadena

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

devuelve 24

Adán
fuente
5

Swift 2.0: Obtenga un recuento: yourString.text.characters.count

Un ejemplo divertido de cómo esto es útil sería mostrar una cuenta regresiva de caracteres de algún número (150 por ejemplo) en un UITextView:

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

En swift4 siempre he usado string.counthasta hoy he encontrado que

string.endIndex.encodedOffset

es la mejor sustitución porque es más rápida: para una cadena de 50 000 caracteres es aproximadamente 6 veces más rápida que .count. El .countdepende de la longitud de la cadena, pero .endIndex.encodedOffsetno lo hace.

Pero hay un NO. No es bueno para cadenas con emojis, dará un resultado incorrecto, por lo que solo.count es correcto.

VYT
fuente
3

En Swift 4 : si la cadena no contiene caracteres unicode, utilice lo siguiente

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

Si la cadena contiene caracteres unicode, utilice lo siguiente:

let spain = "España"
let count1 = spain.count // output 6
let count2 = spain.utf8.count // output 7
Ashis Laha
fuente
¿Por qué querrías usar utf8.count? Eso no da la cuenta de personajes. Da la cantidad de bytes necesarios para la codificación UTF-8 de la cadena.
rmaddy
2

En Xcode 6.1.1

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

Creo que los brainiacs cambiarán esto en cada versión menor.

usuario3812138
fuente
2

Obtenga el valor de cadena de su vista de texto o campo de texto:

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

Encuentra el recuento de los caracteres en la cadena:

let numberOfChars = textlength.characters.count
kalyan711987
fuente
2

Esto es lo que terminé haciendo

let replacementTextAsDecimal = Double(string)

if string.characters.count > 0 &&
    replacementTextAsDecimal == nil &&
    replacementTextHasDecimalSeparator == nil {
        return false
}
Bryan Clark
fuente
Creo que está tratando de hacer más que solo obtener la longitud de la cadena, y en cualquier caso esto parece incompleto (¿no debería haber también un return truecaso?). ¿Puede verificar dos veces y, en caso de que edite su respuesta? ¡Gracias!
Fabio dice reinstalar a Mónica el
2

Actualización de Swift 4 en comparación con Swift 3

Swift 4 elimina la necesidad de una matriz de caracteres en String. Esto significa que puede llamar directamente counta una cadena sin obtener primero la matriz de caracteres.

"hello".count                  // 5

Mientras que en Swift 3, tendrá que obtener la matriz de caracteres y luego contar el elemento en esa matriz. Tenga en cuenta que este siguiente método todavía está disponible en swift 4.0, ya que aún puede llamar characterspara acceder a la matriz de caracteres de la cadena dada

"hello".characters.count       // 5

Swift 4.0 también adopta Unicode 9 y ahora puede interpretar grupos de grafemas. Por ejemplo, contar con un emoji le dará 1 mientras que en swift 3.0, puede obtener recuentos superiores a 1.

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

Swift 4

let str =  "Your name"

str.count 

Recuerde: el espacio también se cuenta en el número

Sr. Shin
fuente
2

Puede obtener la longitud simplemente escribiendo una extensión:

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
    }
}
Riajur Rahman
fuente
1
var str = "Hello, playground"
var newString = str as NSString    

countElements(str)

Esto cuenta los caracteres en Cadena Swift regular

countElements((newString as String))    

Esto cuenta los caracteres en un NSString

Brokenrhino
fuente
1

La mejor manera de contar String en Swift es esta:

var str = "Hello World"
var length = count(str.utf16)
Zaldy
fuente
2
Deberías usar solo count (str). Intente usar su cuenta (str.utf16) con avance de subcadena ()
Leo Dabus el
1

String y NSString son un puente gratuito para que pueda utilizar todos los métodos disponibles para NSString con Swift String

let x = "test" as NSString
let y : NSString = "string 2"
let lenx = x.count
let leny = y.count
Tien Dinh
fuente
1
test1.characters.count

le dará el número de letras / números, etc. en su cadena.

ex:

test1 = "StackOverflow"

print(test1.characters.count)

( imprime " 13 ")

Andy Lebowitz
fuente
1

Apple lo hizo diferente de otros idiomas principales. La forma actual es llamar:

test1.characters.count

Sin embargo, para tener cuidado, cuando dices longitud, te refieres al recuento de caracteres, no al recuento de bytes, porque esos dos pueden ser diferentes cuando usas caracteres que no son ascii.

Por ejemplo; "你好啊hi".characters.countle dará 5 pero este no es el recuento de los bytes. Para obtener el recuento real de bytes, debe hacerlo "你好啊hi".lengthOfBytes(using: String.Encoding.utf8). Esto te dará 11.

Franco
fuente
1

En este momento (en Swift 2.3) si usa:

myString.characters.count 

el método devolverá un tipo de "Distancia", si necesita el método para devolver un Entero, debe escribir cast de la siguiente manera:

var count = myString.characters.count as Int
Jesse
fuente
2
El Distancede String.CharacterView es Int , no debería haber ninguna necesidad de este reparto.
Martin R