Respuestas:
Si. A partir de Swift 3.0, si necesita el índice para cada elemento junto con su valor, puede usar el enumerated()
método para iterar sobre la matriz. Devuelve una secuencia de pares compuestos por el índice y el valor de cada elemento de la matriz. Por ejemplo:
for (index, element) in list.enumerated() {
print("Item \(index): \(element)")
}
Antes de Swift 3.0 y después de Swift 2.0, la función se llamaba enumerate()
:
for (index, element) in list.enumerate() {
print("Item \(index): \(element)")
}
Antes de Swift 2.0, enumerate
era una función global.
for (index, element) in enumerate(list) {
println("Item \(index): \(element)")
}
enumerate
?
enumerating
por Swift 4. ¡Emocionante!
for (index, element) in
cuando se usa enumerated
es engañoso. debería serfor (offset, element) in
Swift 5 proporciona un método llamado enumerated()
para Array
. enumerated()
tiene la siguiente declaración:
func enumerated() -> EnumeratedSequence<Array<Element>>
Devuelve una secuencia de pares (n, x), donde n representa un número entero consecutivo que comienza en cero yx representa un elemento de la secuencia.
En los casos más simples, puede usar enumerated()
con un bucle for. Por ejemplo:
let list = ["Car", "Bike", "Plane", "Boat"]
for (index, element) in list.enumerated() {
print(index, ":", element)
}
/*
prints:
0 : Car
1 : Bike
2 : Plane
3 : Boat
*/
Sin embargo, tenga en cuenta que no está limitado a usar enumerated()
con un bucle for. De hecho, si planea usar enumerated()
un bucle for para algo similar al siguiente código, lo está haciendo mal:
let list = [Int](1...5)
var arrayOfTuples = [(Int, Int)]()
for (index, element) in list.enumerated() {
arrayOfTuples += [(index, element)]
}
print(arrayOfTuples) // prints [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
Una forma más rápida de hacer esto es:
let list = [Int](1...5)
let arrayOfTuples = Array(list.enumerated())
print(arrayOfTuples) // prints [(offset: 0, element: 1), (offset: 1, element: 2), (offset: 2, element: 3), (offset: 3, element: 4), (offset: 4, element: 5)]
Como alternativa, también puede usar enumerated()
con map
:
let list = [Int](1...5)
let arrayOfDictionaries = list.enumerated().map { (a, b) in return [a : b] }
print(arrayOfDictionaries) // prints [[0: 1], [1: 2], [2: 3], [3: 4], [4: 5]]
Además, aunque tiene algunas limitaciones , forEach
puede ser un buen reemplazo para un bucle for:
let list = [Int](1...5)
list.reversed().enumerated().forEach { print($0, ":", $1) }
/*
prints:
0 : 5
1 : 4
2 : 3
3 : 2
4 : 1
*/
Al usar enumerated()
y makeIterator()
, incluso puede iterar manualmente en su Array
. Por ejemplo:
import UIKit
import PlaygroundSupport
class ViewController: UIViewController {
var generator = ["Car", "Bike", "Plane", "Boat"].enumerated().makeIterator()
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(type: .system)
button.setTitle("Tap", for: .normal)
button.frame = CGRect(x: 100, y: 100, width: 100, height: 100)
button.addTarget(self, action: #selector(iterate(_:)), for: .touchUpInside)
view.addSubview(button)
}
@objc func iterate(_ sender: UIButton) {
let tuple = generator.next()
print(String(describing: tuple))
}
}
PlaygroundPage.current.liveView = ViewController()
/*
Optional((offset: 0, element: "Car"))
Optional((offset: 1, element: "Bike"))
Optional((offset: 2, element: "Plane"))
Optional((offset: 3, element: "Boat"))
nil
nil
nil
*/
enumerate
?
Encontré esta respuesta mientras buscaba una manera de hacerlo con un Diccionario , y resulta que es bastante fácil adaptarlo, solo pasa una tupla para el elemento.
// Swift 2
var list = ["a": 1, "b": 2]
for (index, (letter, value)) in list.enumerate() {
print("Item \(index): \(letter) \(value)")
}
Simplemente puede usar el ciclo de enumeración para obtener el resultado deseado:
Swift 2:
for (index, element) in elements.enumerate() {
print("\(index): \(element)")
}
Swift 3 y 4:
for (index, element) in elements.enumerated() {
print("\(index): \(element)")
}
O simplemente puede pasar por un bucle for para obtener el mismo resultado:
for index in 0..<elements.count {
let element = elements[index]
print("\(index): \(element)")
}
Espero eso ayude.
for (index, element) in arrayOfValues.enumerate() {
// do something useful
}
o con Swift 3 ...
for (index, element) in arrayOfValues.enumerated() {
// do something useful
}
Sin embargo, con mayor frecuencia uso enumerate en combinación con map o filter. Por ejemplo, con operar en un par de matrices.
En esta matriz, quería filtrar elementos indexados impares o pares y convertirlos de Ints a Dobles. Entonces enumerate()
obtiene su índice y el elemento, luego el filtro verifica el índice y, finalmente, para deshacerme de la tupla resultante, lo mapeo solo al elemento.
let evens = arrayOfValues.enumerate().filter({
(index: Int, element: Int) -> Bool in
return index % 2 == 0
}).map({ (_: Int, element: Int) -> Double in
return Double(element)
})
let odds = arrayOfValues.enumerate().filter({
(index: Int, element: Int) -> Bool in
return index % 2 != 0
}).map({ (_: Int, element: Int) -> Double in
return Double(element)
})
Usando .enumerate()
trabajos, pero no proporciona el índice verdadero del elemento; solo proporciona un Int que comienza con 0 y se incrementa en 1 para cada elemento sucesivo. Esto suele ser irrelevante, pero existe la posibilidad de un comportamiento inesperado cuando se usa con el ArraySlice
tipo. Toma el siguiente código:
let a = ["a", "b", "c", "d", "e"]
a.indices //=> 0..<5
let aSlice = a[1..<4] //=> ArraySlice with ["b", "c", "d"]
aSlice.indices //=> 1..<4
var test = [Int: String]()
for (index, element) in aSlice.enumerate() {
test[index] = element
}
test //=> [0: "b", 1: "c", 2: "d"] // indices presented as 0..<3, but they are actually 1..<4
test[0] == aSlice[0] // ERROR: out of bounds
Es un ejemplo un tanto artificial, y no es un problema común en la práctica, pero creo que vale la pena saber que esto puede suceder.
it does not actually provide the true index of the element; it only provides an Int beginning with 0 and incrementing by 1 for each successive element
Sí, por eso se llama enumerar . Además, el segmento no es una matriz, por lo que no sorprende que se comporte de manera diferente. No hay ningún error aquí: todo es por diseño. :)
filter
primero?
Para completar, simplemente puede iterar sobre los índices de su matriz y usar el subíndice para acceder al elemento en el índice correspondiente:
let list = [100,200,300,400,500]
for index in list.indices {
print("Element at:", index, " Value:", list[index])
}
Usando para cada
list.indices.forEach {
print("Element at:", $0, " Value:", list[$0])
}
Usando el enumerated()
método de recolección . Tenga en cuenta que devuelve una colección de tuplas con el offset
y el element
:
for item in list.enumerated() {
print("Element at:", item.offset, " Value:", item.element)
}
utilizando forEach:
list.enumerated().forEach {
print("Element at:", $0.offset, " Value:", $0.element)
}
Esos imprimirán
Elemento en: 0 Valor: 100
Elemento en: 1 Valor: 200
Elemento en: 2 Valor: 300
Elemento en: 3 Valor: 400
Elemento en: 4 Valor: 500
Si necesita el índice de matriz (no el desplazamiento) y su elemento, puede extender la Colección y crear su propio método para obtener los elementos indexados:
extension Collection {
func indexedElements(body: ((index: Index, element: Element)) throws -> Void) rethrows {
var index = startIndex
for element in self {
try body((index,element))
formIndex(after: &index)
}
}
}
Otra posible implementación según lo sugerido por Alex es comprimir los índices de colección con sus elementos:
extension Collection {
func indexedElements(body: ((index: Index, element: Element)) throws -> Void) rethrows {
for element in zip(indices, self) { try body(element) }
}
}
Pruebas:
let list = ["100","200","300","400","500"]
list.dropFirst(2).indexedElements {
print("Index:", $0.index, "Element:", $0.element)
}
Esto p [rint
Índice: 2 Elemento: 300
Índice: 3 Elemento: 400
Índice: 4 Elemento: 500
enumeratedIndices
haciendo un bucle conzip(self.indices, self)
for element in zip(indices, self) { try body(element) }
. Por cierto, no me gusta el nombre que elegí, indexedElements
podría describir mejor lo que hace
for
bucle funciona, pero tambiénzip(self.indices, self) .forEach(body)
forEach
hace un bucle for detrás de escena. Prefiero mantenerlo simple github.com/apple/swift/blob/master/stdlib/public/core/… @inlinable public func forEach( _ body: (Element) throws -> Void ) rethrows { for element in self { try body(element) } } }
Xcode 8 y Swift 3: la matriz se puede enumerar usando tempArray.enumerated()
Ejemplo:
var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for (index, item) in someStrs.enumerated()
{
print("Value at index = \(index) is \(item)").
}
consola:
Value at index = 0 is Apple
Value at index = 1 is Amazon
Value at index = 2 is Google
Para aquellos que quieran usar forEach
.
Swift 4
extension Array {
func forEachWithIndex(_ body: (Int, Element) throws -> Void) rethrows {
try zip((startIndex ..< endIndex), self).forEach(body)
}
}
O
array.enumerated().forEach { ... }
Para lo que desea hacer, debe usar el enumerated()
método en su matriz :
for (index, element) in list.enumerated() {
print("\(index) - \(element)")
}
Llamamos a la función enumerate para implementar esto. me gusta
for (index, element) en array.enumerate () {
// index es indexposition de la matriz
// elemento es elemento de la matriz
}