[머릿말]
Swift를 사용하여 코딩 테스트를 준비하던 중 입력을 받는 과정에서 split과 components를 사용하는 것을 보았다. 두 가지 모두 설정한 문자를 기준으로 입력받은 문자열을 구분한다는 점은 같아 보이는데 어떤 차이점이 있는지 궁금하여 찾아보게되었다.
1. split(separator:maxSplits:ommittingEmptySubsequences:)
split에 대한 Apple Developer Document의 내용은 아래와 같다.
❗️
func split(separator: Character, maxSplits: Int = Int.max, omittingEmptySubsequences: Bool = true) -> [Substring]
func split(
separator: Self.Element,
maxSplits: Int = Int.max,
omittingEmptySubsequences: Bool = true
) -> [Self.SubSequence]
Returns the longest possible subsequences of the collection, in order, around elements equal to the given element. (주어진 요소와 동일한 요소를 순서에 맞게 컬렉션의 가능한 제일 긴 부분 문자열을 반환한다.)
Parameters
- separator: The element that should be split upon.
- maxSplits: The maximum number of times to split the collection, or one less than the number of subsequences to return. If maxSplits + 1 subsequences are returned, the last one is a suffix of the original collection containing the remaining elements. maxSplits must be greater than or equal to zero. The default value is Int.max.
- ommittingEmptySubseqnences: If false, an empty subsequence is returned in the result for each consecutive pair of separator elements in the collection and for each instance of separator at the start or end of the collection. If true, only nonempty subsequences are returned. The default value is true.
Return Value
An array of subsequences, split from this collection's elements.
❗️
split( )은 문자열에 대해 정의한 구분자를 기준으로 나눠 부분 문자열의 배열로 만들어주는 기능을 한다. 입력을 받고 공백을 기준으로 이를 분리하여 저장할 때 많이 사용된다. 매개변수는 총 3개가 있으며 내용은 아래와 같다.
- separator: 문자열을 나눌 기준이 될 문자로써 반드시 입력해야 한다.
let myStr = "hello hello hello hello"
print(myStr.split(separator: " ")) // 공백을 기준으로 분리
// ["hello", "hello", "hello", "hello"]
- maxSplits: 최대 나눌 횟수로써 기본값은 Int.max이다. 이는 반드시 0 이상이어야 하며 만약 음수 값을 사용하면 오류가 발생한다.
let myStr = "hello hello hello hello"
print(myStr.split(separator: " ", maxSplits: 2)) // 공백을 기준으로 2번만 분리
// ["hello", "hello", "hello hello"]
- omittingEmptySubsequences: 문자열의 맨 앞 또는 맨 뒤에 구분자(separator)가 존재할 때 이를 빈 문자열("")로 추가할지 말지를 나타내는 것으로써 기본값은 true이다. true일 땐 빈 문자열을 추가하지 않으며, false일 땐 빈 문자열을 추가한다. 이는 거의 사용되지 않는 매개변수다.
let myStr = " hello hello hello hello "
print(myStr.split(separator: " ", omittingEmptySubsequences: false)) // 맨앞, 맨뒤 구분자를 빈 문자열로 추가
// ["", "hello", "hello", "hello", "hello", ""]
print(myStr.split(separator: " ", omittingEmptySubsequences: true)) // 맨앞, 맨뒤 구분자를 무시(기본값)
// ["hello", "hello", "hello", "hello"]
2. components(separatedBy:)
components에 대한 Apple Developer Document의 내용은 아래와 같다.
❗️
func components(separatedBy separator: String) -> [String]
/// Returns an array containing substrings from the string
/// that have been divided by characters in the given set.
public func components(separatedBy separator: CharacterSet) -> [String]
Returns an array containing substrings from the receiver that have been divided by a given separator.
Parameters
- separatedBy: The separator string.
Return Value
An NSArray object containing substrings from the receiver that have been divided by separator.
❗️
components도 split과 동일하게 설정한 구분자로 문자열을 구분짓는 기능을 한다. components를 사용하기 위해서는 Foundataion Framework를 import해야 한다. 매개변수로는 separatedBy 1개만 받는다.
- separatedBy: 문자열을 나눌 기준으로 사용할 문자 또는 문자열 또는 문자 집합이다. split과는 다르게 여러 문자를 구분자로 설정할 수 있다.
import Foundation
let myStr = " hello A hello B hello C hello "
print(myStr.components(separatedBy: ["A", "B", "C"]))
// ["hello ", " hello ", " hello C"]
3. split과 components의 차이점?
그렇다면 이렇게 같은 기능을 하는 두 메서드의 차이점은 무엇일까? 분명 각각을 사용하는 이유가 있을 것이고, 상황에 따라 사용이 권장되는 것이 있을 것이다. 하나씩 살펴보자.
1. 구분자(separator)의 개수가 한 개 vs 여러 개
split의 구분자는 한 개만 사용할 수 있고, components의 구분자는 여러 개를 사용할 수 있다. 여러 구분자를 기준으로 문자열을 잘라야 하는 상황엔 components를 사용하면 된다.
2. 반환형이 Array<Substring> vs Array<String>
split의 반환형은 Substring 타입 배열이고, components의 반환형은 String 타입 배열이다.
import Foundation
let myStr = " hello hello hello "
let res1 = myStr.split(separator: " ")
print(type(of: res1)) // Array<Substring>
let res2 = myStr.components(separatedBy: " ")
print(type(of: res2)) // Array<String>
3. 맨 뒤 문자가 구분자일 때 무시 vs 빈 문자열
split은 omittingEmptySubsequences의 값이 false가 아닌 이상 맨 앞, 맨 뒤에 오는 구분자는 무시해버린다. 그러나 components는 이를 무시하지 않고 빈 문자열로 저장한다.
import Foundation
let myStr = " hello hello hello "
let res1 = myStr.split(separator: " ")
print(res1) // ["hello", "hello", "hello"]
let res2 = myStr.components(separatedBy: " ")
print(res2) // ["", "hello", "hello", "hello", ""]
4. split이 components보다 빠르다
앞서 split의 반환형은 Array<Substring>이라 했고 components의 반환형은 Array<String>이라 했다. Substring은 참조(reference)만 사용하고 새 문자열을 메모리에 할당하지 않는다. 따라서 String 타입의 components보다 속도가 빠르다.
*참고)
component(separatedBy:) versus .split(separator: )
In Swift 4, new method .split(separator:) is introduced by apple in String struct. So to split a string with whitespace which is faster for e.g.. let str = "My name is Sudhir" str.components(
stackoverflow.com
components가 먼저 사용되다가 Swift4에서 split이 새롭게 추가된 것이라고 한다.
그래서 매개변수로 split이 더 많고, 속도도 더 빠른 것 같다.
구분자를 여러 개 사용해야 하는 경우를 제외하고는 split을 사용하면 될 것 같다.
끝!