Jawaban:
Iya. Pada Swift 3.0, jika Anda memerlukan indeks untuk setiap elemen beserta nilainya, Anda dapat menggunakan enumerated()
metode ini untuk beralih ke array. Ini mengembalikan urutan pasangan yang terdiri dari indeks dan nilai untuk setiap item dalam array. Sebagai contoh:
for (index, element) in list.enumerated() {
print("Item \(index): \(element)")
}
Sebelum Swift 3.0 dan setelah Swift 2.0, fungsinya disebut enumerate()
:
for (index, element) in list.enumerate() {
print("Item \(index): \(element)")
}
Sebelum Swift 2.0, enumerate
adalah fungsi global.
for (index, element) in enumerate(list) {
println("Item \(index): \(element)")
}
enumerate
?
enumerating
untuk Swift 4. Menyenangkan!
for (index, element) in
saat menggunakan enumerated
itu menyesatkan. seharusnyafor (offset, element) in
Swift 5 menyediakan sebuah metode yang disebut enumerated()
untuk Array
. enumerated()
memiliki deklarasi berikut:
func enumerated() -> EnumeratedSequence<Array<Element>>
Mengembalikan urutan pasangan (n, x), di mana n merupakan bilangan bulat berturut-turut mulai dari nol dan x mewakili elemen urutan.
Dalam kasus paling sederhana, Anda dapat menggunakan enumerated()
dengan for loop. Sebagai contoh:
let list = ["Car", "Bike", "Plane", "Boat"]
for (index, element) in list.enumerated() {
print(index, ":", element)
}
/*
prints:
0 : Car
1 : Bike
2 : Plane
3 : Boat
*/
Perhatikan bahwa Anda tidak terbatas untuk menggunakan enumerated()
dengan for loop. Bahkan, jika Anda berencana untuk menggunakan enumerated()
dengan for loop untuk sesuatu yang mirip dengan kode berikut, Anda salah melakukannya:
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)]
Cara yang lebih cepat untuk melakukan ini adalah:
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)]
Sebagai alternatif, Anda juga dapat menggunakan enumerated()
dengan 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]]
Selain itu, meskipun memiliki beberapa keterbatasan , forEach
bisa menjadi pengganti yang baik untuk for for:
let list = [Int](1...5)
list.reversed().enumerated().forEach { print($0, ":", $1) }
/*
prints:
0 : 5
1 : 4
2 : 3
3 : 2
4 : 1
*/
Dengan menggunakan enumerated()
dan makeIterator()
, Anda bahkan dapat mengulang secara manual di Array
. Sebagai contoh:
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
?
Saya menemukan jawaban ini sambil mencari cara untuk melakukannya dengan Kamus , dan ternyata cukup mudah untuk mengadaptasinya, cukup berikan tuple untuk elemen tersebut.
// Swift 2
var list = ["a": 1, "b": 2]
for (index, (letter, value)) in list.enumerate() {
print("Item \(index): \(letter) \(value)")
}
Anda cukup menggunakan loop enumerasi untuk mendapatkan hasil yang Anda inginkan:
Swift 2:
for (index, element) in elements.enumerate() {
print("\(index): \(element)")
}
Swift 3 & 4:
for (index, element) in elements.enumerated() {
print("\(index): \(element)")
}
Atau Anda bisa melalui loop for untuk mendapatkan hasil yang sama:
for index in 0..<elements.count {
let element = elements[index]
print("\(index): \(element)")
}
Semoga ini bisa membantu.
for (index, element) in arrayOfValues.enumerate() {
// do something useful
}
atau dengan Swift 3 ...
for (index, element) in arrayOfValues.enumerated() {
// do something useful
}
Namun, saya paling sering menggunakan enumerate dalam kombinasi dengan peta atau filter. Misalnya dengan mengoperasikan beberapa array.
Dalam array ini saya ingin memfilter elemen yang aneh atau bahkan diindeks dan mengubahnya dari Ints ke Doubles. Jadi enumerate()
membuat Anda mengindeks dan elemen, lalu menyaring memeriksa indeks, dan akhirnya untuk menyingkirkan tuple yang dihasilkan saya memetakannya hanya elemen.
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)
})
Menggunakan .enumerate()
karya, tetapi tidak memberikan indeks sebenarnya dari elemen; itu hanya memberikan Int yang diawali dengan 0 dan bertambah 1 untuk setiap elemen berurutan. Ini biasanya tidak relevan, tetapi ada potensi untuk perilaku yang tidak terduga ketika digunakan dengan ArraySlice
tipe tersebut. Ambil kode berikut:
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
Ini adalah contoh yang agak dibuat-buat, dan itu bukan masalah umum dalam praktiknya, tetapi saya pikir tetap berharga mengetahui hal ini bisa terjadi.
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
Ya, itu sebabnya ini disebut enumerate . Selain itu, slice bukan array, jadi tidak mengherankan jika berperilaku berbeda. Tidak ada bug di sini - semuanya sesuai desain. :)
filter
terlebih dahulu?
Untuk kelengkapan Anda dapat dengan mudah beralih pada indeks array Anda dan menggunakan subskrip untuk mengakses elemen pada indeks yang sesuai:
let list = [100,200,300,400,500]
for index in list.indices {
print("Element at:", index, " Value:", list[index])
}
Menggunakan forEach
list.indices.forEach {
print("Element at:", $0, " Value:", list[$0])
}
Menggunakan enumerated()
metode pengumpulan . Perhatikan bahwa ia mengembalikan koleksi tupel dengan offset
dan element
:
for item in list.enumerated() {
print("Element at:", item.offset, " Value:", item.element)
}
menggunakan forEach:
list.enumerated().forEach {
print("Element at:", $0.offset, " Value:", $0.element)
}
Itu akan dicetak
Elemen pada: 0 Nilai: 100
Elemen pada: 1 Nilai: 200
Elemen pada: 2 Nilai: 300
Elemen pada: 3 Nilai: 400
Elemen pada: 4 Nilai: 500
Jika Anda membutuhkan indeks array (bukan offset) dan elemennya, Anda dapat memperluas Koleksi dan membuat metode Anda sendiri untuk mendapatkan elemen yang diindeks:
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)
}
}
}
Kemungkinan implementasi lain seperti yang disarankan oleh Alex adalah meng-zip indeks koleksi dengan elemen-elemennya:
extension Collection {
func indexedElements(body: ((index: Index, element: Element)) throws -> Void) rethrows {
for element in zip(indices, self) { try body(element) }
}
}
Pengujian:
let list = ["100","200","300","400","500"]
list.dropFirst(2).indexedElements {
print("Index:", $0.index, "Element:", $0.element)
}
Ini akan p [rintis
Indeks: 2 Elemen: 300
Indeks: 3 Elemen: 400
Indeks: 4 Elemen: 500
enumeratedIndices
dengan looping over denganzip(self.indices, self)
for element in zip(indices, self) { try body(element) }
. Tapi saya tidak suka penamaan yang saya pilih, indexedElements
mungkin menggambarkan lebih baik apa yang dilakukannya
for
loop bekerja, tetapi jugazip(self.indices, self) .forEach(body)
forEach
melakukan perulangan untuk di belakang layar. Saya lebih suka menjaganya agar tetap sederhana 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 dan Swift 3: Array dapat dihitung menggunakan tempArray.enumerated()
Contoh:
var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for (index, item) in someStrs.enumerated()
{
print("Value at index = \(index) is \(item)").
}
menghibur:
Value at index = 0 is Apple
Value at index = 1 is Amazon
Value at index = 2 is Google
Bagi yang ingin menggunakan forEach
.
Cepat 4
extension Array {
func forEachWithIndex(_ body: (Int, Element) throws -> Void) rethrows {
try zip((startIndex ..< endIndex), self).forEach(body)
}
}
Atau
array.enumerated().forEach { ... }
Untuk apa yang ingin Anda lakukan, Anda harus menggunakan enumerated()
metode pada Array Anda :
for (index, element) in list.enumerated() {
print("\(index) - \(element)")
}
Kami memanggil fungsi enumerate untuk mengimplementasikan ini. Suka
untuk (indeks, elemen) di array.enumerate () {
// index adalah indexposition of array
// elemen adalah elemen array
}