Risposte:
Sì. A partire da Swift 3.0, se è necessario l'indice per ciascun elemento insieme al suo valore, è possibile utilizzare il enumerated()
metodo per scorrere sull'array. Restituisce una sequenza di coppie composta dall'indice e dal valore per ciascun elemento dell'array. Per esempio:
for (index, element) in list.enumerated() {
print("Item \(index): \(element)")
}
Prima di Swift 3.0 e dopo Swift 2.0, la funzione era chiamata enumerate()
:
for (index, element) in list.enumerate() {
print("Item \(index): \(element)")
}
Prima di Swift 2.0, enumerate
era una funzione globale.
for (index, element) in enumerate(list) {
println("Item \(index): \(element)")
}
enumerate
?
enumerating
per Swift 4. Emozionante!
for (index, element) in
quando si usa enumerated
è fuorviante. dovrebbe esserefor (offset, element) in
Swift 5 fornisce un metodo chiamato enumerated()
per Array
. enumerated()
ha la seguente dichiarazione:
func enumerated() -> EnumeratedSequence<Array<Element>>
Restituisce una sequenza di coppie (n, x), dove n rappresenta un numero intero consecutivo a partire da zero e x rappresenta un elemento della sequenza.
Nei casi più semplici, è possibile utilizzare enumerated()
con un ciclo for. Per esempio:
let list = ["Car", "Bike", "Plane", "Boat"]
for (index, element) in list.enumerated() {
print(index, ":", element)
}
/*
prints:
0 : Car
1 : Bike
2 : Plane
3 : Boat
*/
Nota comunque che non sei limitato all'uso enumerated()
con un ciclo for. In effetti, se prevedi di utilizzare enumerated()
un ciclo for per qualcosa di simile al seguente codice, stai sbagliando:
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)]
Un modo più veloce per farlo è:
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)]
In alternativa, puoi anche utilizzare 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]]
Inoltre, sebbene abbia alcune limitazioni , forEach
può essere un buon sostituto di un ciclo for:
let list = [Int](1...5)
list.reversed().enumerated().forEach { print($0, ":", $1) }
/*
prints:
0 : 5
1 : 4
2 : 3
3 : 2
4 : 1
*/
Usando enumerated()
e makeIterator()
, puoi anche iterare manualmente sul tuo Array
. Per esempio:
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
?
Ho trovato questa risposta mentre cercavo un modo per farlo con un dizionario , e risulta abbastanza facile adattarlo, basta passare una tupla per l'elemento.
// Swift 2
var list = ["a": 1, "b": 2]
for (index, (letter, value)) in list.enumerate() {
print("Item \(index): \(letter) \(value)")
}
Puoi semplicemente usare il ciclo di enumerazione per ottenere il risultato desiderato:
Swift 2:
for (index, element) in elements.enumerate() {
print("\(index): \(element)")
}
Swift 3 e 4:
for (index, element) in elements.enumerated() {
print("\(index): \(element)")
}
Oppure puoi semplicemente passare attraverso un ciclo for per ottenere lo stesso risultato:
for index in 0..<elements.count {
let element = elements[index]
print("\(index): \(element)")
}
Spero che sia d'aiuto.
for (index, element) in arrayOfValues.enumerate() {
// do something useful
}
o con Swift 3 ...
for (index, element) in arrayOfValues.enumerated() {
// do something useful
}
Tuttavia, il più delle volte uso enumerate in combinazione con mappa o filtro. Ad esempio, operando su un paio di array.
In questo array volevo filtrare elementi pari o dispari e convertirli da Ints a Doppio. Quindi enumerate()
ottieni l'indice e l'elemento, quindi il filtro controlla l'indice e, infine, per sbarazzarmi della tupla risultante, la mappa solo sull'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)
})
Utilizzando .enumerate()
funziona, ma non fornisce il vero indice dell'elemento; fornisce solo un Int che inizia con 0 e aumenta di 1 per ogni elemento successivo. Questo di solito è irrilevante, ma esiste il potenziale per un comportamento imprevisto se utilizzato con il ArraySlice
tipo. Prendi il seguente codice:
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
È un esempio un po 'inventato, e in pratica non è un problema comune, ma penso comunque che valga la pena sapere che ciò può accadere.
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ì, ecco perché si chiama enumerate . Inoltre, slice non è un array, quindi nessuna sorpresa si comporta diversamente. Non c'è nessun bug qui - tutto è di progettazione. :)
filter
primo?
Per completezza, puoi semplicemente scorrere gli indici dell'array e utilizzare il pedice per accedere all'elemento nell'indice corrispondente:
let list = [100,200,300,400,500]
for index in list.indices {
print("Element at:", index, " Value:", list[index])
}
Usando forOach
list.indices.forEach {
print("Element at:", $0, " Value:", list[$0])
}
Utilizzando il enumerated()
metodo di raccolta . Nota che restituisce una raccolta di tuple con il offset
e il element
:
for item in list.enumerated() {
print("Element at:", item.offset, " Value:", item.element)
}
usando forOach:
list.enumerated().forEach {
print("Element at:", $0.offset, " Value:", $0.element)
}
Quelli stamperanno
Elemento a: 0 Valore: 100
Elemento a: 1 Valore: 200
Elemento a: 2 Valore: 300
Elemento a: 3 Valore: 400
Elemento a: 4 Valore: 500
Se hai bisogno dell'indice di array (non dell'offset) e del suo elemento, puoi estendere Collection e creare il tuo metodo per ottenere gli elementi indicizzati:
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)
}
}
}
Un'altra possibile implementazione suggerita da Alex è comprimere gli indici di raccolta con i suoi elementi:
extension Collection {
func indexedElements(body: ((index: Index, element: Element)) throws -> Void) rethrows {
for element in zip(indices, self) { try body(element) }
}
}
test:
let list = ["100","200","300","400","500"]
list.dropFirst(2).indexedElements {
print("Index:", $0.index, "Element:", $0.element)
}
Questo p [rint
Indice: 2 Elemento: 300
Indice: 3 Elemento: 400
Indice: 4 Elemento: 500
enumeratedIndices
ripetendo ciclicamente conzip(self.indices, self)
for element in zip(indices, self) { try body(element) }
. A proposito, non mi piace il nome che ho scelto, indexedElements
potrebbe descrivere meglio cosa fa
for
ciclo, ma anchezip(self.indices, self) .forEach(body)
forEach
fa un ciclo for dietro le quinte. Preferisco mantenerlo semplice 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 e Swift 3: l'array può essere elencato usando tempArray.enumerated()
Esempio:
var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for (index, item) in someStrs.enumerated()
{
print("Value at index = \(index) is \(item)").
}
console:
Value at index = 0 is Apple
Value at index = 1 is Amazon
Value at index = 2 is Google
Per coloro che vogliono usare forEach
.
Swift 4
extension Array {
func forEachWithIndex(_ body: (Int, Element) throws -> Void) rethrows {
try zip((startIndex ..< endIndex), self).forEach(body)
}
}
O
array.enumerated().forEach { ... }
Per ciò che si desidera fare, è necessario utilizzare il enumerated()
metodo sull'array :
for (index, element) in list.enumerated() {
print("\(index) - \(element)")
}
Abbiamo chiamato la funzione di enumerazione per implementare questo. piace
per (indice, elemento) in array.enumerate () {
// index è indicizzazione dell'array
// element è element di array
}