Yanıtlar:
Evet. Swift 3.0'dan itibaren, her öğenin değeriyle birlikte dizine ihtiyacınız varsa , diziyi yinelemek için enumerated()
yöntemi kullanabilirsiniz . Dizideki her öğe için dizinden ve değerden oluşan bir çift dizi döndürür. Örneğin:
for (index, element) in list.enumerated() {
print("Item \(index): \(element)")
}
Swift 3.0'dan önce ve Swift 2.0'dan sonra, fonksiyon çağrıldı enumerate()
:
for (index, element) in list.enumerate() {
print("Item \(index): \(element)")
}
Swift 2.0'dan önce enumerate
küresel bir işlev vardı.
for (index, element) in enumerate(list) {
println("Item \(index): \(element)")
}
enumerate
mı?
enumerating
Swift 4 için uçağa geçecekler . Heyecan verici!
for (index, element) in
kullanırken enumerated
yanıltıcıdır. olmalıfor (offset, element) in
Swift 5 adı verilen bir yöntem sağlar enumerated()
için Array
. enumerated()
aşağıdaki beyanı içerir:
func enumerated() -> EnumeratedSequence<Array<Element>>
Bir çift dizisini (n, x) döndürür; burada n, sıfırdan başlayarak ardışık bir tamsayıyı temsil eder ve x, dizinin bir öğesini temsil eder.
En basit durumlarda, enumerated()
for döngüsü ile kullanabilirsiniz . Örneğin:
let list = ["Car", "Bike", "Plane", "Boat"]
for (index, element) in list.enumerated() {
print(index, ":", element)
}
/*
prints:
0 : Car
1 : Bike
2 : Plane
3 : Boat
*/
Bununla enumerated()
birlikte, for döngüsü ile kullanmakla sınırlı olmadığınızı unutmayın . Aslında, enumerated()
aşağıdaki koda benzer bir şey için bir for döngüsü ile kullanmayı planlıyorsanız , yanlış yapıyorsunuz:
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)]
Bunu yapmanın en hızlı yolu:
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)]
Alternatif olarak, aynı zamanda kullanabilir enumerated()
ile 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]]
Bazı olmasına rağmen Dahası, sınırlamaları , forEach
döngü için iyi bir yedek olabilir:
let list = [Int](1...5)
list.reversed().enumerated().forEach { print($0, ":", $1) }
/*
prints:
0 : 5
1 : 4
2 : 3
3 : 2
4 : 1
*/
Kullanarak enumerated()
ve makeIterator()
, hatta sizinle ilgili şu elle yineleme yapabilirsiniz Array
. Örneğin:
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
mı?
İstediğiniz sonucu elde etmek için numaralandırma döngüsünü kullanabilirsiniz:
Hızlı 2:
for (index, element) in elements.enumerate() {
print("\(index): \(element)")
}
Hızlı 3 ve 4:
for (index, element) in elements.enumerated() {
print("\(index): \(element)")
}
Ya da aynı sonucu elde etmek için bir for döngüsünden geçebilirsiniz:
for index in 0..<elements.count {
let element = elements[index]
print("\(index): \(element)")
}
Umarım yardımcı olur.
for (index, element) in arrayOfValues.enumerate() {
// do something useful
}
veya Swift 3 ile ...
for (index, element) in arrayOfValues.enumerated() {
// do something useful
}
Ancak, enumerate öğesini harita veya filtreyle birlikte kullanıyorum. Örneğin, birkaç dizide çalışırken.
Bu dizide tek veya hatta dizine alınmış öğeleri filtrelemek ve bunları Ints'ten Çiftler'e dönüştürmek istedim. Böylece enumerate()
indeksi ve elemanı alır, daha sonra filtre indeksi kontrol eder ve son olarak ortaya çıkan demetten kurtulmak için onu sadece elemanla eşleştiririm.
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)
})
.enumerate()
Çalışmaları kullanmak , ancak öğenin gerçek dizinini sağlamaz; birbirini izleyen her öğe için yalnızca 0 ile başlayan ve 1 ile artan bir Int sağlar. Bu genellikle ilgisizdir, ancak türle birlikte kullanıldığında beklenmedik davranış potansiyeli vardır ArraySlice
. Aşağıdaki kodu alın:
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
Bu biraz çelişkili bir örnek ve pratikte yaygın bir sorun değil ama yine de bunun olabileceğini bilmeye değer olduğunu düşünüyorum.
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
Evet, bu yüzden numaralandırma denir . Ayrıca, dilim dizi değildir, bu yüzden sürpriz farklı davranır. Burada bir hata yok - her şey tasarım gereğidir. :)
filter
ilk kullanıyorsanız ?
Tamlık için dizi dizinleriniz üzerinde yineleme yapabilir ve ilgili dizindeki öğeye erişmek için alt simge kullanabilirsiniz:
let list = [100,200,300,400,500]
for index in list.indices {
print("Element at:", index, " Value:", list[index])
}
ForEach kullanımı
list.indices.forEach {
print("Element at:", $0, " Value:", list[$0])
}
Toplama enumerated()
yöntemini kullanma . Not onunla küpe koleksiyonu döndüren offset
ve element
:
for item in list.enumerated() {
print("Element at:", item.offset, " Value:", item.element)
}
forEach kullanarak:
list.enumerated().forEach {
print("Element at:", $0.offset, " Value:", $0.element)
}
Bunlar yazdıracak
Eleman: 0 Değer: 100
Element değeri: 1 Değer: 200
Element değeri: 2 Değer: 300
Element değeri: 3 Değer: 400
Elemanda: 4 Değer: 500
Dizi dizinine (ofset değil) ve elemanına ihtiyacınız varsa, Koleksiyonu genişletebilir ve dizinlenmiş öğeleri almak için kendi yönteminizi oluşturabilirsiniz:
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)
}
}
}
Alex'in önerdiği bir başka olası uygulama, toplama endekslerini unsurlarıyla sıkıştırmaktır:
extension Collection {
func indexedElements(body: ((index: Index, element: Element)) throws -> Void) rethrows {
for element in zip(indices, self) { try body(element) }
}
}
Test yapmak:
let list = ["100","200","300","400","500"]
list.dropFirst(2).indexedElements {
print("Index:", $0.index, "Element:", $0.element)
}
Bu p [rint
Dizin: 2 Eleman: 300
Dizin: 3 Eleman: 400
Dizin: 4 Eleman: 500
enumeratedIndices
ile üzerinde döngü ilezip(self.indices, self)
for element in zip(indices, self) { try body(element) }
. Btw Ben seçtiğim adlandırma sevmiyorum, indexedElements
ne yaptığını daha iyi açıklayabilir
for
döngü işe yarıyor, ama aynı zamandazip(self.indices, self) .forEach(body)
forEach
perde arkasında for döngüsü yapıyor. Basit tutmayı tercih ediyorum 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 ve Swift 3: Dizi kullanılarak numaralandırılabilir tempArray.enumerated()
Misal:
var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for (index, item) in someStrs.enumerated()
{
print("Value at index = \(index) is \(item)").
}
konsolu:
Value at index = 0 is Apple
Value at index = 1 is Amazon
Value at index = 2 is Google
Kullanmak isteyenler için forEach
.
Hızlı 4
extension Array {
func forEachWithIndex(_ body: (Int, Element) throws -> Void) rethrows {
try zip((startIndex ..< endIndex), self).forEach(body)
}
}
Veya
array.enumerated().forEach { ... }
Yapmanız isteyen ne için, kullanması gereken enumerated()
senin üzerine yöntemini Array :
for (index, element) in list.enumerated() {
print("\(index) - \(element)")
}
Bunu uygulamak için numaralandırma fonksiyonunu çağırdık. sevmek
array.enumerate () içindeki (dizin, öğe) için {
// dizin, dizinin dizin konumlandırmasıdır
// öğesi dizinin öğesidir
}