arrays - visual - ¿Puede una matriz[AnyObject] ser transferida opcionalmente a una matriz específica de tipo?
que es un array en programacion (2)
Estoy leyendo la documentación de Swift, mirando la sección sobre el casting de tipos.
La documentación habla sobre cómo obtener una matriz de tipo [AnyObject]
desde los marcos de Foundation (lo que sería una NSArray *
en Objective-C).
Primero, la documentación proporciona este ejemplo:
for object in someObjects {
let movie = object as Movie
println("Movie: ''/(movie.name)'', dir. /(movie.director)")
}
Ahora, quiero cambiar el ejemplo ligeramente, a un caso en el que no sé que todos los objetos son de tipo Movie
, así que haría esto:
for object in someObject {
if let movie = object as? Movie {
println("Movie: ''/(movie.name'', dir. /(movie.director)")
}
}
La documentación luego proporciona un ejemplo de una mejor manera de escribir el primer bucle:
for movie in someObjects as [Movie] {
println("Movie: ''/(movie.name)'', dir. /(movie.director)")
}
Donde bajamos algunos someObjects
de un [AnyObject]
a un [Movie]
para que no tengamos que bajar en el bucle.
Y esto me hizo pensar, ¿puede la matriz ser una opción abatida como un todo?
if let someMovies = someObjects as? [Movie] {
for movie in someMovies {
println("Movie: ''/(movie.name)'', dir. /(movie.director)")
}
}
¿Esto funciona? Y si es así, ¿qué tan malo es esto desde el punto de vista del rendimiento? ¿Cuánto tiempo tomaría verificar el tipo de cada objeto en una matriz de 10,000 elementos usando el downcast opcional?
Entiendo que las implicaciones entre este fragmento y mi fragmento anterior anterior opcional son diferentes. La primera recorrerá cada objeto y solo intentará imprimir si el objeto es una Movie
, mientras que la segunda solo entrará en el bucle si la matriz puede ser invertida a una matriz [Movie]
, en cuyo caso imprimirá todas o ninguna. , pero puedo imaginar que hay situaciones en las que esto sería preferible.
Intentemos esto
var someObjects = [
NSString(),
NSUUID()
]
let uuids = someObjects as? NSUUID[]
uuids
es nulo
var someOtherObjects = [
NSUUID(),
NSUUID()
]
let all_uuids = someOtherObjects as? NSUUID[]
all_uuids
es igual a someOtherObjects
Así que parece que funciona. Puede usar la expresión para probar si todos los elementos de la matriz son del tipo esperado pero no filtrará la matriz para seleccionar solo el tipo esperado.
Lo tienes, funciona exactamente como tu código de ejemplo:
let strings = ["Hi", "Hello", "Aloha"]
let anyObjects: [AnyObject] = strings
if let downcastStrings = anyObjects as? [String] {
println("It''s a [String]")
}
// console says "It''s a [String]"
No tengo idea sobre el rendimiento, pero no asumo que tendrá que recorrer toda la matriz para determinar si es posible una caída hacia abajo.
Así que sentí curiosidad y realicé una prueba rápida con 100,000 valores simples en un par de configuraciones diferentes de [AnyObject]
, donde estoy tratando de reducir la matriz a un [String]
frente a los elementos individuales:
// var anyObjects: [AnyObject] = [AnyObject]()
// filled with random assortment of Int, String, Double, Bool
Running test with mixed array
downcast array execution time = 0.000522
downcast elements execution time = 0.571749
// var actuallyStrings: [AnyObject] = [AnyObject]()
// filled with String values
Running test with all strings
downcast array execution time = 1.141267
downcast elements execution time = 0.853765
Parece que es súper rápido descartar la matriz mixta como no descargable, ya que solo necesita escanear hasta encontrar un elemento que no sea String
. Para una matriz que puede abatirse, claramente tiene que atravesar toda la matriz y toma mucho más tiempo, aunque no estoy seguro de por qué no es la misma velocidad que recorrer la matriz y revisar manualmente cada elemento.