본문은 야곰 아카데미 커리어 스타터 캠프를 통해 학습한 내용을 회고한 글입니다.
forEach
forEach를 알아보기 전에 for-in문부터 알아보도록 하겠다.
for-in문
배열에 있는 요소, 특정 범위의 숫자, String 안의 Character와 같은시퀀스를 반복하기 위해서 for-in문을 사용한다.
다음은 배열에 있는 요소들을 반복하기 위해 for-in문을 사용한 예시이다:
let days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
for day in days {
print("Today is \(day)")
}
//Today is Monday
//Today is Tuesday
//Today is Wednesday
//Today is Thursday
//Today is Friday
//Today is Saturday
//Today is Sunday
배열 뿐만 아니라, 딕셔너리에 대해서도 key-value짝을 이루어서 반복을 할 수 있다. 딕셔너리를 반복시킬 때, 딕셔너리에 있는 각각의 요소들은 (key, value) 튜플로서 반환된다. 그리고 for-in문의 바디 안에서 (key, value)튜플의 멤버를 명시적인 상수로 분리할 수 있기도 하다.
다음의 예시를 보자:
let month = [1: "January", 2: "February", 3: "March", 4: "April", 5: "May", 6: "June", 7: "July", 8: "August", 9: "September", 10: "October", 11: "November", 12: "December"]
for (key, value) in month {
print("month \(key): \(value)")
}
//month 5: May
//month 9: September
//month 1: January
//month 7: July
//month 10: October
//month 2: February
//month 11: November
//month 6: June
//month 12: December
//month 3: March
//month 8: August
//month 4: April
딕셔너리의 내용물은 본질적으로 순서가 없다. 그렇기 때문에 딕셔너리를 반복하는 것은 어떤 요소가 나올지에 대한 순서를 보장하지 못한다. 딕셔너리에 요소를 넣은 순서가 그 요소들이 반복될 순서를 정의해주진 않는다는 것이다.
숫자 범위에 대해서도 for-in문을 돌릴 수 있다:
for index in 1...9 {
print("\(index) times 3 is \(index*3)")
}
//1 times 3 is 3
//2 times 3 is 6
//3 times 3 is 9
//4 times 3 is 12
//5 times 3 is 15
//6 times 3 is 18
//7 times 3 is 21
//8 times 3 is 24
//9 times 3 is 27
1부터 9까지의 반복되는 시퀀스는 범위 연산자(...)의 사용으로 명시되어있다. 인덱스의 값은 그 범위의 첫번째 값인 1로 설정이 된다. 이 경우에, 이 루프는 현재 index에 대한 구구단 3단을 프린트하는 하나의 문장만을 가지고 있다. 이 문장이 실행되고 나서, index의 값은 그 범위의 두 번째 값인 2를 갖게된다. 그리고 print메서드가 다시 호출된다. 이 과정은 범위의 끝에 도달할 때까지 반복한다.
위의 예시에서는 index가 자동적으로 루프의 반복에 따라 값이 설정되는 상수였다. 이런 경우에는, index가 사용되기 전에 선언될 필요가 없다. index가 루프의 선언에서 암시적으로 포함되어 선언되기 때문이다.
만약 시퀀스에서의 각각의 값을 필요로 하는게 아니라면, 와일드카드를 통해서 이름을 지어줄 수 있기도 하다:
let base = 3
let power = 10
var answer = 1
for _ in 1...power {
answer *= base
}
print("\(base) to the power of \(power) is \(answer)")
// Prints "3 to the power of 10 is 59049"
위의 예시는 base의 power승이 되는 숫자를 계산하고 있다. 1에다가 3을 10번 곱하는 방식으로 이루어진다. 이 때, 이 계산에서 각각의 카운터 값은 불필요하다. 그래서 와일드카드를 사용했고, 각각의 값은 반복을 돌면서 현재의 값에 접근을 하지 않게 된다.
stride(from:to:by:) 메서드를 이용해 띄엄띄엄 값을 설정할 수도 있다:
let minuteInterval = 5
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
// render the tick mark every 5 minutes (0, 5, 10, 15 ... 45, 50, 55)
}
stride(from:through:by:)를 사용해서 값을 설정해줄 수도 있다:
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
// render the tick mark every 3 hours (3, 6, 9, 12)
}
forEach
func forEach(_ body: (Self.Element) throws -> Void) rethrows
for-in문과 같은 기능을 한다:
let names = ["Rhode", "Christy", "Hyemory", "Moori"]
for name in names {
print(name)
}
//Rhode
//Christy
//Hyemory
//Moori
names.forEach { name in
print(name)
}
//Rhode
//Christy
//Hyemory
//Moori
다음과 같이 축약하여 쓸 수도 있다:
names.forEach { name in
print(name)
}
//Rhode
//Christy
//Hyemory
//Moori
names.forEach { print($0) }
//Rhode
//Christy
//Hyemory
//Moori
딕셔너리에 대해서도 반복을 돌릴 수 있다:
let month = [1: "January", 2: "February", 3: "March", 4: "April", 5: "May", 6: "June", 7: "July", 8: "August", 9: "September", 10: "October", 11: "November", 12: "December"]
for (key, value) in month {
print("month \(key): \(value)")
}
//month 12: December
//month 7: July
//month 4: April
//month 11: November
//month 5: May
//month 2: February
//month 1: January
//month 3: March
//month 6: June
//month 8: August
//month 9: September
//month 10: October
month.forEach { (key, value) in
print("month \(key): \(value)")
}
//month 12: December
//month 7: July
//month 4: April
//month 11: November
//month 5: May
//month 2: February
//month 1: January
//month 3: March
//month 6: June
//month 8: August
//month 9: September
//month 10: October
딕셔너리도 마찬가지로 다음과 같이 축약하여 쓸 수 있다:
month.forEach { (key, value) in
print("month \(key): \(value)")
}
//month 12: December
//month 6: June
//month 11: November
//month 10: October
//month 4: April
//month 3: March
//month 1: January
//month 7: July
//month 8: August
//month 2: February
//month 5: May
//month 9: September
month.forEach { print("month \($0): \($1)") }
//month 12: December
//month 6: June
//month 11: November
//month 10: October
//month 4: April
//month 3: March
//month 1: January
//month 7: July
//month 8: August
//month 2: February
//month 5: May
//month 9: September
for-in문과 forEach의 차이점
continue&break
for-in문은 직접 구현하는 반복문이다. 하지만, forEach는 내가 반복하고 싶은 구문을 forEach라는 함수의 파라미터로 클로저로 작성해서 넘겨주는 메서드이다. 그러므로 반복문 안에서만 사용할 수 있는 contine, break는 for-in문에서는 사용가능하지만, forEach에서는 사용불가하다.
return
for-in문은 위에서 언급했듯 직접 구현하는 반복문이다. 그러므로 반복문을 돌다가 return을 만나면 함수 자체가 종료된다. 하지만 forEach의 경우, 반복문이 아닌 클로저를 전달하기 때문에 return을 만나면 전달한 클로저만이 종료된다. 그렇기 때문에 반복 횟수에 영향을 주지 않는다.
compactMap
compactMap은 다음과 같이 사용된다:
배열.compactMap { 요소에 대한 조건 }
조건에 맞게 기존의 element를 변환해 새로운 배열값을 반환하는 메서드이다. 어떤 element가 조건에 맞지 않아 nil이 될 경우, 그 element를 제외하고 배열을 만든다. 조건에 맞는 요소들은 옵셔널바인딩이 된다.
let randomArray = ["1", "a", "2", "-", "3", "개발자", "4", "5", "가수", "건물주", "배우", "6"]
let intArray = randomArray.compactMap { Int($0) }
print(intArray) //[1, 2, 3, 4, 5, 6]
참조
https://docs.swift.org/swift-book/LanguageGuide/ControlFlow.html
https://developer.apple.com/documentation/swift/sequence/foreach(_:)
https://babbab2.tistory.com/95
'YAGOM CAREER STARTER' 카테고리의 다른 글
[토요스터디A반] 20230204: 고차함수 (0) | 2023.02.06 |
---|---|
[TIL] 20230131: - (0) | 2023.02.06 |
[TIL] 20230127: Type Properties (0) | 2023.01.28 |
[TIL] 20230126: SOLID (0) | 2023.01.28 |
[TIL] 20230124: Generics (0) | 2023.01.26 |