Swift에서 인덱스와 요소로 루프를 반복하는 방법


784

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

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

답변:


1660

예. 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)")
}

3
튜플처럼 보이지만 Swift 1.2에서는 2.0에 대해 확실하지 않습니다. enumerate는 EnumerateSequence <base : SequenceType> 구조체를 반환합니다.
nstein

2
@Leviathlon 눈에 띄거나 측정 가능한 성능 오버 헤드가 중요합니까? 호
댄 Rosenstark는

를 사용하면 인덱스에 액세스 할 수있는 유일한 이점은 enumerate무엇입니까?
Honey

29
어쩌면 그들은 enumerating스위프트 4 를 위해 거런 드로 바뀔 것입니다 .
Dan Rosenstark

3
@Honey를 for (index, element) in사용할 때 enumerated오해의 소지가 있습니다. 해야for (offset, element) in
레오 버스들이시길

115

스위프트 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
 */

1
인덱스에 대한 액세스 권한을 얻는 것이 유일한 이점 enumerate입니까?
Honey

52

Swift 2부터는 다음과 같이 컬렉션에서 열거 함수를 호출해야합니다.

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

47

Dictionary 를 사용 하여이 작업을 수행하는 방법을 찾고있는 동안이 대답을 찾았 으며 쉽게 적응할 수 있으며 요소에 튜플을 전달하면됩니다.

// Swift 2

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

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

18

열거 형 루프를 사용하여 원하는 결과를 얻을 수 있습니다.

스위프트 2 :

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

스위프트 3 & 4 :

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

또는 단순히 for 루프를 통해 동일한 결과를 얻을 수 있습니다.

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

도움이 되길 바랍니다.


14

기본 열거

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

또는 스위프트 3과 함께 ...

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

열거, 필터 및 맵

그러나 가장 자주 맵 또는 필터와 함께 열거 형을 사용합니다. 예를 들어, 몇 개의 어레이에서 작동하는 경우.

이 배열에서 홀수 또는 짝수 색인 요소를 필터링하고 Ints에서 Doubles로 변환하려고했습니다. 따라서 enumerate()인덱스와 요소를 가져온 다음 필터는 인덱스를 확인하고 결과 튜플을 제거하기 위해 요소에 매핑합니다.

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

9

.enumerate()작품을 사용 하지만 요소의 실제 색인을 제공하지는 않습니다. 연속적인 각 요소에 대해 0으로 시작하고 1 씩 증가하는 Int 만 제공합니다. 일반적으로 관련이 없지만 ArraySlice유형 과 함께 사용하면 예기치 않은 동작이 발생할 수 있습니다 . 다음 코드를 사용하십시오.

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

그것은 다소 고안된 예이며, 실제로 일반적인 문제는 아니지만 여전히 이것이 일어날 수 있다는 것을 알 가치가 있다고 생각합니다.


2
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그렇기 때문에 enumerate 라고 합니다. 또한 slice는 배열이 아니므로 다르게 동작하는 것은 놀라운 일이 아닙니다. 여기에는 버그가 없습니다. 모든 것은 의도적으로 설계된 것입니다. :)
Eric Aya

5
사실이지만 결코 버그라고 부르지 않았습니다. ArraySlice 유형과 어떻게 부정적으로 상호 작용할 수 있는지 알지 못하는 사람들에게는 언급 할 가치가 있다고 생각한 것은 예상치 못한 행동 일뿐입니다.
Cole Campbell

실제 요소의 색인을 얻는 방법을 알고 있습니까 (예 : filter처음 사용하는 경우) ?
Alexandre Cassagne

9

스위프트 3부터는

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

9

완전성을 위해 배열 인덱스를 반복하고 첨자를 사용하여 해당 인덱스의 요소에 액세스 할 수 있습니다.

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

forEach 사용

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

수집 enumerated()방법을 사용합니다 . offset및로 구성된 튜플 모음을 반환 합니다 element.

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

forEach 사용 :

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

그 인쇄됩니다

에 요소 : 0 값 : 100

요소 : 1 값 : 200

요소 : 2 값 : 300

요소 : 3 값 : 400

에 요소 : 4 값 : 500

배열 인덱스 (오프셋이 아닌)와 해당 요소가 필요한 경우 Collection을 확장하고 색인이 지정된 요소를 얻는 고유 한 메서드를 만들 수 있습니다.

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가 제안한 또 다른 가능한 구현은 컬렉션 인덱스를 요소로 압축하는 것입니다.

extension Collection {
    func indexedElements(body: ((index: Index, element: Element)) throws -> Void) rethrows {
        for element in zip(indices, self) { try body(element) }
    }
}

테스트 :

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

이것은 헹굴 것이다

색인 : 2 요소 : 300

색인 : 3 요소 : 400

색인 : 4 요소 : 500


BTWenumeratedIndiceszip(self.indices, self)
Alexander – Reinstate Monica

@ Alexander-ReinstateMonica for element in zip(indices, self) { try body(element) }. Btw 내가 선택한 이름이 마음에 들지 않고, indexedElements그 기능을 더 잘 설명 할 수 있습니다.
Leo Dabus

더 나은 이름이라고 생각합니다. 네, for루프 작동뿐만 아니라zip(self.indices, self) .forEach(body)
알렉산더 - 분석 재개 모니카

@ Alexander-ReinstateMonica forEach는 무대 뒤에서 for 루프를 수행합니다. 나는 그것을 단순하게 유지하는 것을 선호한다. 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) } } }
Leo

7

이것은 열거 형 루프의 공식입니다.

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

자세한 내용은 여기 를 확인하십시오 .


5

개인적으로 forEach방법을 선호합니다 .

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

짧은 버전을 사용할 수도 있습니다.

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

4

Xcode 8 및 Swift 3 : 배열을 사용하여 열거 가능 tempArray.enumerated()

예:

var someStrs = [String]()

someStrs.append("Apple")  
someStrs.append("Amazon")  
someStrs += ["Google"]    


for (index, item) in someStrs.enumerated()  
{  
        print("Value at index = \(index) is \(item)").  
}

콘솔:

Value at index = 0 is Apple
Value at index = 1 is Amazon
Value at index = 2 is Google

3

사용하고자하는 사람들을 위해 forEach.

스위프트 4

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

또는

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

2

당신이하고 싶은 일을 위해, 당신은 Array 에서 enumerated()메소드를 사용해야합니다 :

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

-1

이것을 구현하기 위해 enumerate 함수를 호출했습니다. 처럼

array.enumerate ()에서 (index, element)

// 인덱스는 배열의 인덱스입니다

// element는 배열의 요소입니다

}

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.