ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Swift의 문자열 처리 (split vs components)
    Swift 2023. 1. 6. 09:08

    안녕하세요. 그린입니다🍏

    이번 포스팅에서는 Swift에서의 문자열 처리를 해주는 두 메서드 split과 components에 대해 학습해보겠습니다🙌

     

    Swift 언어의 특성상 문자열을 타 언어보다 다루기가 조금 까다로워요🥲

    쉽게 Subscript를 통해 Int 인덱스 참조가 불가능하여 쉽게 문자열에서의 문자를 빼올 수 도 없고 index를 통해서 가능하게 해주죠.

    이와 관련해서 Swift에서는 도대체 왜 그런지 궁금하시다면 아래 포스팅을 먼저 보고 오셔도 좋습니다!

    https://green1229.tistory.com/286

     

    Subscript에 대해 알아보기 (feat.String)

    안녕하세요. 그린입니다🍏 오늘 포스팅은 Subscript에 대해 알아보며 Swift 언어에서만 왜 String을 다룰때 Subscript가 어떻게 다른지 알아보겠습니다🙌 우선 Subscript라는것 많이 들어보셨을것 같아요

    green1229.tistory.com

     

    그럼 이어서 오늘 할 주제는 Swift의 문자열을 분리시키는 두 메서드를 알아보겠습니다.
    문자열을 분리시킨다는 목적은 동일한데 실제로 어떻게 다른지 하나씩 짚어볼께요🕺🏻

     

    split(separator:maxSplits:omittingEmptySubsequences:)

    우선 공식문서에서는 split은 지정된 요소와 동일한 요소 주변에서 컬렉션의 가능한 가장 긴 하위 시퀀스를 순서대로 반환한다고 합니다.

    String 타입의 인스턴스 메서드이구요.

    지정된 요소라 치면 앞으로 알아볼 구분자를 뜻하는것 같습니다.

    선언은 아래와 같습니다.

    func split(
        separator: Self.Element,
        maxSplits: Int = Int.max,
        omittingEmptySubsequences: Bool = true
    ) -> [Self.SubSequence]

    보시면 세개의 파라미터를 받아요. 하나씩 어떤 역할을 하는지 보겠습니다ㅎㅎ

     

     1. separator

    문자열 분리를 위해 어떤 구분자를 가지고 분리를 해줄 지에 대한 요소입니다.

    예를들어 아래 코드를 보시죠.

    let str = "I am Green"
    let splitedStr = str.split(separator: " ")
    
    print(splitedStr) // ["I", "am", "Green"]

    띄어쓰기 즉 공백을 구분자로 두었을때 3개의 문자열 서브시퀀스로 나눠집니다.

     

    그럼 하나 더 보시죠!

    let str = "I am Green"
    let splitedStr = str.split(separator: "am")
    
    // error

    이렇게 만약 문자열을 구분자로 두면 String.Element의 구분자 타입이 아님으로 컴파일 에러가 발생합니다.

    즉, 구분자에는 Character 타입만 들어가야 됩니다🙋🏻

     

    그럼 공백이 아닌 속한 문자를 넣는다면 어떻게 될까요?

    let str = "I am Green"
    let splitedStr = str.split(separator: "a")
    
    print(splitedStr) // ["I ", "m Green"]

    이렇게 구분자 기준으로 분리가 됩니다.

     

    마지막으로 문자열에 들어있지 않는 구분자 문자를 주게 되면 어떻게 될까요?

    let str = "I am Green"
    let splitedStr = str.split(separator: "b")
    
    print(splitedStr) // ["I am Green"]

    문자열 자체를 서브시퀀스 배열로 리턴해줍니다!

     

    그럼 얼추 separator에 대해서는 감이 오셨을거라 생각하고 두번째 요소로 넘어가겠습니다🕺🏻

     

    2. maxSplits

    분리할 최대 횟수를 지정할 수 있습니다.

    기본값으로는 거의 무한정인 Int max값이에요.

    즉 따로 지정하지 않으면 구분자를 통해 모두 분리시킵니다.

    그럼 지정해준다면 어떨지 한번 보시죠!

    let str = "I am Green"
    let splitedStr = str.split(separator: " ", maxSplits: 1)
    
    print(splitedStr) // ["I", "am Green"]

    요렇게 공백은 2개 존재하지만 맥스값으로준 1의 공백 갯수 만큼만 분리시킵니다.

    am과 Green 사이에도 공백이 있지만 이미 맥스값 1개를 넘었기에 합쳐서 분리가 됩니다.

     

    자 이것도 아주 쉽죠! 그럼 조금 처음보는 omittingEmptySubsequences에 대해 알아보겠습니다🕺🏻

     

    3. omittingEmptySubsequences

    omit이라는 단어는 생략을 의미합니다.

    빈 서브시퀀스를 생략한다는 옵션 같아요.

    우선 Bool 타입으로 기본 값은 true입니다.

    true로 되있기에 별도 설정이 없다면 마지막 요소에 빈 서브시퀀스를 제외하고 반환해주게 되요.

    즉 아래와 같이 우리가 쉽게 볼 수 있는 형식이죠.

    let str = "I am Green "
    let splitedStr = str.split(separator: " ", omittingEmptySubsequences: true)
    
    print(splitedStr) // ["I", "am", "Green"]

    만약 false라면 마지막 요소에 빈 서브시퀀스를 추가하여 반환해줍니다.

    이렇게 되겠죠?

    let str = "I am Green "
    let splitedStr = str.split(separator: " ", omittingEmptySubsequences: false)
    
    print(splitedStr) // ["I", "am", "Green", ""]

    마지막 요소에 빈 서브시퀀스가 추가된것을 확인하실 수 있습니다ㅎㅎ

    정리해볼께요!

    true면 비어 있지 않은 하위 시퀀스만 반환하고 false면 비어있는 시퀀스도 반환해줍니다🙌

     

    split의 반환 타입은 SubSequence 타입으로 서브시퀀스는 ArraySlice의 별칭입니다.

    ArraySlice에 대해서는 조만간 포스팅을 해보겠습니다ㅎㅎ

     

    참고로 split의 시간 복잡도는 컬렉션의 길이만큼인 O(n)을 가지게 됩니다🥸

     

    그럼 이어서 components에 대해 알아보시죠📣

     

    components(separatedBy:)

    split과 역할은 동일하지만 조금 더 간단할 수 있습니다.

    파라미터가 보시면 하나밖에 없거든요ㅎㅎ

    공식문서에서는 지정된 구분자로 나눠진 하위 문자열을 포함하는 문자열 배열을 반환한다고 합니다.

    func components(separatedBy separator: String) -> [String]

     

    메서드 시그니쳐를 보시면 Split에서는 Character 타입을 구분자로 받았지만 components는 String, 즉 문자열을 구분자로 받습니다.

    split에서는 아래와 같이 문자열로 쪼갤 수 없었다면 components는 가능합니다.

    let str = "I am Green"
    let splitedStr = str.components(separatedBy: "am")
    
    print(splitedStr) // ["I ", " Green"]

    다만 components는 Foundation 프레임워크에 속해 있기에 Foundation을 임포트 해줘야합니다!

     

    split vs components의 성능차이

    둘의 성능적으로의 큰 차이는 구분자를 빈 문자열로 두고 문자열 내에 연속된 빈 공백 문자가 많을때 차이가 납니다.

    왜냐하면 split에서는 omittingEmptySubsequences라는 옵션이 있어 빈 시퀀스를 제외해줄 수 있죠.

    아래 예시를 보시죠!

    let str = "I am Green         "
    let splitedStr = str.split(separator: " ")
    
    print(splitedStr) // ["I", "am", "Green"]

    Green 뒤에 많은 공백이 들어가도 빈 시퀀스를 제거해줍니다.

    그런데 components는 어떨까요?

    let str = "I am Green       "
    let splitedStr = str.components(separatedBy: " ")
    
    print(splitedStr) // ["I", "am", "Green", "", "", "", "", "", "", ""]

    이렇게 빈 시퀀스를 제외하지 않고 있습니다.

    즉 이러한 빈 시퀀스가 많아진다면 components의 성능은 당연히 split보다 낮아질것입니다👀

    이러한 부분들을 참고해서 골라 사용하면 좋을것 같네요!

     

    마무리

    split과 components를 다루는것에 있어 딥하게 들어가면 정말 많은 차이점을 가지고 있었네요.

    사실 프로젝트를 진행하면서 다뤘던것보다 알고리즘을 학습하고 문제를 풀면서 다뤄봤던 경험이 더 많은것 같아요.

    그래도 명확한 차이를 이번에 확실히 짚고 넘어가게 되었습니다🥸

     

    [참고 자료]

    https://developer.apple.com/documentation/swift/string/split(separator:maxsplits:omittingemptysubsequences:) 

     

    Apple Developer Documentation

     

    developer.apple.com

    https://developer.apple.com/documentation/foundation/nsstring/1413214-components

     

    Apple Developer Documentation

     

    developer.apple.com

    'Swift' 카테고리의 다른 글

    ArraySlice  (3) 2023.01.12
    Opaque Types  (4) 2023.01.09
    addingPercentEncoding(withAllowedCharacters:)  (5) 2023.01.02
    Subscript에 대해 알아보기 (feat.String)  (4) 2022.10.03
    정규 표현식 (Regex)  (0) 2022.09.13
Designed by Tistory.