Development Tip

Swift for 루프 : 인덱스, 배열 요소?

yourdevel 2020. 9. 29. 18:46
반응형

Swift for 루프 : 인덱스, 배열 요소?


파이썬의 열거와 같이 배열을 반복하고 인덱스와 요소를 모두 갖는 데 사용할 수있는 함수가 있습니까?

for index, element in enumerate(list):
    ...

예. Swift 3.0부터는 값과 함께 각 요소에 대한 인덱스가 필요한 경우 enumerated()메서드 를 사용하여 배열을 반복 할 수 있습니다 . 배열의 각 항목에 대한 인덱스와 값으로 구성된 일련의 쌍을 반환합니다. 예를 들면 :

for (index, element) in list.enumerated() {
  print("Item \(index): \(element)")
}

Swift 3.0 이전과 Swift 2.0 이후에 함수가 호출되었습니다 enumerate().

for (index, element) in list.enumerate() {
    print("Item \(index): \(element)")
}

Swift 2.0 이전에는 enumerate전역 함수였습니다.

for (index, element) in enumerate(list) {
    println("Item \(index): \(element)")
}

스위프트 5라는 방법을 제공 enumerated()하기위한을 Array. enumerated()다음과 같은 선언이 있습니다.

func enumerated() -> EnumeratedSequence<Array<Element>>

쌍의 시퀀스 (n, x)를 반환합니다. 여기서 n은 0에서 시작하는 연속 정수를 나타내고 x는 시퀀스의 요소를 나타냅니다.


가장 간단한 경우 enumerated()에는 for 루프와 함께 사용할 수 있습니다 . 예를 들면 :

let list = ["Car", "Bike", "Plane", "Boat"]
for (index, element) in list.enumerated() {
    print(index, ":", element)
}

/*
prints:
0 : Car
1 : Bike
2 : Plane
3 : Boat
*/

그러나 enumerated()for 루프와 함께 사용하도록 제한되지 않습니다 . 사실, enumerated()다음 코드와 유사한 것을 위해 for 루프와 함께 사용하려는 경우 잘못하고있는 것입니다.

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)]

이를 수행하는 더 빠른 방법은 다음과 같습니다.

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)]

대안으로 다음 enumerated()과 함께 사용할 수도 있습니다 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]]

그것은 어떤 갖지만 또한, 제한 , forEach루프에 대한 좋은 대체 될 수있다 :

let list = [Int](1...5)
list.reversed().enumerated().forEach { print($0, ":", $1) }

/*
prints:
0 : 5
1 : 4
2 : 3
3 : 2
4 : 1
*/

enumerated()을 사용 makeIterator()하면 Array. 예를 들면 :

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
 */

Swift 2부터 enumerate 함수는 다음과 같이 컬렉션에서 호출되어야합니다.

for (index, element) in list.enumerate() {
    print("Item \(index): \(element)")
}

I found this answer while looking for a way to do that with a Dictionary, and it turns out it's quite easy to adapt it, just pass a tuple for the element.

// Swift 2

var list = ["a": 1, "b": 2]

for (index, (letter, value)) in list.enumerate() {
    print("Item \(index): \(letter) \(value)")
}

You can simply use loop of enumeration to get your desired result:

Swift 2:

for (index, element) in elements.enumerate() {
    print("\(index): \(element)")
}

Swift 3 & 4:

for (index, element) in elements.enumerated() {
    print("\(index): \(element)")
}

Or you can simply go through a for loop to get the same result:

for index in 0..<elements.count {
    let element = elements[index]
    print("\(index): \(element)")
}

Hope it helps.


Basic enumerate

for (index, element) in arrayOfValues.enumerate() {
// do something useful
}

or with Swift 3...

for (index, element) in arrayOfValues.enumerated() {
// do something useful
}

Enumerate, Filter and Map

However, I most often use enumerate in combination with map or filter. For example with operating on a couple of arrays.

In this array I wanted to filter odd or even indexed elements and convert them from Ints to Doubles. So enumerate() gets you index and the element, then filter checks the index, and finally to get rid of the resulting tuple I map it to just the element.

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)
                        })

Starting with Swift 3, it is

for (index, element) in list.enumerated() {
  print("Item \(index): \(element)")
}

This is the Formula of loop of Enumeration:

for (index, value) in shoppingList.enumerate() {
print("Item \(index + 1): \(value)")
}

for more detail you can check Here.


Using .enumerate() works, but it does not provide the true index of the element; it only provides an Int beginning with 0 and incrementing by 1 for each successive element. This is usually irrelevant, but there is the potential for unexpected behavior when used with the ArraySlice type. Take the following code:

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

It's a somewhat contrived example, and it's not a common issue in practice but still I think it's worth knowing this can happen.


For completeness you can simply iterate over your array indices and use subscript to access the element at the corresponding index:

let list = [100,200,300,400,500]
for index in list.indices {
    print("Element at:", index, " Value:", list[index])
}

Using forEach

list.indices.forEach {
    print("Element at:", $0, " Value:", list[$0])
}

Using collection enumerated() method. Note that it returns a collection of tuples with the offset and the element:

for item in list.enumerated() {
    print("Element at:", item.offset, " Value:", item.element)
}

using forEach:

list.enumerated().forEach {
    print("Element at:", $0.offset, " Value:", $0.element)
}

Those will print

Element at: 0 Value: 100

Element at: 1 Value: 200

Element at: 2 Value: 300

Element at: 3 Value: 400

Element at: 4 Value: 500

If you need the array index (not the offset) and its element you can extend Collection and create your own method to enumerate its indices:

extension Collection {
    func enumeratedIndices(body: ((index: Index, element: Element)) throws -> ()) rethrows {
        var index = startIndex
        for element in self {
            try body((index,element))
            formIndex(after: &index)
        }
    }
}

Testing:

let list =  ["100","200","300","400","500"]
list.dropFirst(2).enumeratedIndices {
    print("Index:", $0.index, "Element:", $0.element)
}

This will p[rint

Index: 2 Element: 300

Index: 3 Element: 400

Index: 4 Element: 500


For those who want to use forEach.

Swift 4

extension Array {
  func forEachWithIndex(_ body: (Int, Element) throws -> Void) rethrows {
    try zip((startIndex ..< endIndex), self).forEach(body)
  }
}

Or

array.enumerated().forEach { ... }

Xcode 8 and Swift 3: Array can be enumerated using tempArray.enumerated()

Example:

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

I personally prefer using the forEach method:

list.enumerated().forEach { (index, element) in
    ...
}

You can also use the short version:

list.enumerated().forEach { print("index: \($0.0), value: \($0.1)") }

For what you are wanting to do, you should use the enumerated() method on your Array:

for (index, element) in list.enumerated() {
    print("\(index) - \(element)")
}

We called enumerate function to implements this. like

for (index, element) in array.enumerate() {

// index is indexposition of array

// element is element of array

}

참고URL : https://stackoverflow.com/questions/24028421/swift-for-loop-for-index-element-in-array

반응형