Lv 1. 추억 점수 zip & init(uniqueKeysWithValues:)

YeongHyeon Jo·2024년 3월 7일
0

Algorithm

목록 보기
8/10

이번에 추억 점수라는 문제를 풀었는데 사실상 문제의 풀이는 쉬웠다.
각 사람마다 추억점수가 있고, 사진을 보고 존재한는 사람의 추억점수를 더하면 끝이였다.

나의 풀이

1. 인물과 인물의 추억 점수를 매칭한다.

나는 Dictionary를 통해 인물과 추억 점수를 매칭했다.
for 문을 이용하여 추억 점수를 각각 하나씩 넣어주었다.

  • key: 인물의 이름
  • value: 인물의 추억 점수
for (index, person) in name.enumerated() {
	personScore.updateValue(yearning[index], forKey: person)
}
// 실행 결과: ["kain": 1, "may": 5, "radi": 3, "kein": 10]

이렇게 미리 Dictionary에 넣어 놓고 나중에 사진에서 각각 가져오게 한다.

2. 사진에 있는 추억점수를 계산한다.

이중 for 문을 사용해서 사진에서 추억 점수를 모두 더해준다.

for p in photo {
	var score: Int = 0
	for i in p {
		if let personScore = personScore[i] {
			score += personScore
		}
	}
	result.append(score)
}
// 실행 결과: [19, 15, 6]

단순히 이렇게 문제를 풀이하니까 너무 쉽게 결과가 나왔다.
하지만, 다른 사람의 풀이를 보니 조금 당황스럽게 단 두줄로 끝이 났다.
이를 한번 훑어봐야겠다.

다른 사람의 풀이

아래와 같이 단 두 줄로 결과가 나오긴했다.
나는 그래도 return 값에는 변수명 하나가 오는게 좋아서 변수를 하나 지정해서 하긴하는데, 그래도 이렇게 줄일 수 있다니.. 조금 차례대로 분석을 해봐야겠다.

func solution1(_ name:[String], _ yearning:[Int], _ photo:[[String]]) -> [Int] {
    let score: [String: Int] = Dictionary(uniqueKeysWithValues: zip(name, yearning))
    return photo.map { $0.reduce(0) { $0 + (score[$1] ?? 0) } }
}

1. zip

공식문서의 내용을 참조하면 아래와 같은 Function으로 설명되어있다.

Creates a sequence of pairs built out of two underlying sequences.
두 개의 기본 시퀀스로 구성된 쌍의 시퀀스를 만듭니다.

sequence1과 sequence2 2개의 파라미터가 있는데 return값은 튜플의 형태로 나오게 된다.
공식문서에서 아래의 예시를 통해 확인할 수 있다.

두번째 예시를 보면 파라미터 중 sequence2의 길이가 sequence1의 길이보다 긴 경우를 볼 수 있다. 이때는 둘 중 짧은 파라미터를 기준으로 결과가 출력된다.

let words = ["one", "two", "three", "four"]
let numbers = 1...4

for (word, number) in zip(words, numbers) {
    print("\(word): \(number)")
}
// Prints "one: 1"
// Prints "two: 2"
// Prints "three: 3"
// Prints "four: 4"

// 만약의 파라미터의 값의 길이가 다를 경우
let naturalNumbers = 1...Int.max
let zipped = Array(zip(words, naturalNumbers))
// zipped == [("one", 1), ("two", 2), ("three", 3), ("four", 4)]

실제 프로젝트에서 확인을 해보자! 첫번째 예시를 적용하면 아래와 같은 결과를 확인할 수 있었다!

let zipped = Array(zip(name, yearning))
// 실행 결과: [("may", 5), ("kein", 10), ("kain", 1), ("radi", 3)]

2. init(uniqueKeysWithValues:)

공식문서

Creates a new dictionary from the key-value pairs in the given sequence.
지정된 시퀀스의 키-값 쌍에서 새 사전을 만듭니다.

key-value가 있는 값을 파라미터에 넣어 Dictionary형태로 리턴하는 Initializer이다.

공식문서의 예시를 보게되면, 여기에도 zip이 사용되었네.
그렇다면 위에서 zip으로 만들어낸 key-value를 가지고 있는 튜플형태의 값을 넣어서 이를 Dictionary로 만든다는 것이다.

let digitWords = ["one", "two", "three", "four", "five"]
let wordToValue = Dictionary(uniqueKeysWithValues: zip(digitWords, 1...5))
print(wordToValue["three"]!)
// Prints "3"
print(wordToValue)
// Prints "["three": 3, "four": 4, "five": 5, "one": 1, "two": 2]"

그래서 실제로 프로젝트에서 적용하면 내가 풀이한 for문을 사용한 것과 결과가 동일하게 나온다.

let score: [String: Int] = Dictionary(uniqueKeysWithValues: zip(name, yearning))
// 실행 결과: ["may": 5, "kain": 1, "radi": 3, "kein": 10]

나는 Dictionary 형태로 만들기 위해 빈 Dictionary를 만들어서 updateValue로 하나씩 값을 넣어줬는데, 여기는 초기화를 할 때부터 튜플형태의 값을 넣어서 한번에 만들어낸 간단한 방법으로 사용된 것 같다!

3. reduce

공식문서
흔히 고차함수라고 불리는 것 중 하나인 reduce이다!

2개의 파라미터를 가지고 있다.

  • initialResult: 초기값으로 사용할 값으로 클로저가 처음 실행될 때, nextPartialResult로 전달해준다.
  • nextPartialResult: 실행되어 나오는 값으로 계속 새로운 값으로 다음 호출에 사용되거나, 리턴값으로 나오는 클로저

리턴 값으로는 지속적으로 실행되어 쌓인 누적값이다. 만약에 요소가 없다면 initialResult값을 리턴한다.

공식문서의 예시를 보게되면 초기값은 0으로 설정되어 있고, x와 y라는 인자가 계속해서 더해진다.

let numbers = [1, 2, 3, 4]
let numberSum = numbers.reduce(0, { x, y in
    x + y
})
// 0 + 1 = 1
// 1 + 2 = 3
// 3 + 3 = 6
// 6 + 4 = 10
// numberSum == 10

그리하여 실제 프로젝트에는 return값으로 아예 결과값을 반영하였다.
photo의 형태는 [[String]]의 형태로 문자열 배열을 하나 하나씩 결과를 얻어내야한다.
그리하여 map을 사용하여 첫번째 항목부터 진행을 한다.
첫번째 photo[0]에서 reduce를 이용하여 해당 식을 진행하여 아래와 같은 결과를 얻을 수 있다.

["may": 5, "kein": 10, "kain": 1, "radi": 3]
return photo.map { $0.reduce(0) { $0 + (score[$1] ?? 0) } }
// 1. 첫번째 동작 (map)
// ["may", "kein", "kain", "radi"]
// 1-1. 두번째 동작 (reduce)
// 초기값(0) + score["may"] = 0 + 5 = 5
// 5 + score["kein"] = 5 + 10 = 15
// 15 + score["kain"] = 15 + 1 = 16
// 16 + score["radi"] = 16 + 3 = 19
// result = 19

결론

고차함수의 사용으로 코드의 길이가 간결해지는 것을 알 수 있게 되고, 다음번엔 고차함수로 접근해서 문제를 풀이해야겠다고 느꼈다!

profile
my name is hyeon

0개의 댓글

관련 채용 정보