Skip to content

[Algorithm] 파일명 정렬 #111

@hwangJi-dev

Description

@hwangJi-dev

💬 문제

파일명 정렬


💬 Idea

  • HEAD와 NUMBER를 구분해주기

    • HEAD : 숫자가 아닌 첫 부분을 반환. 이 때 HEAD 부분의 대소문자는 정렬 시 구분이 되지 않아도 되므로 lowercased()를 적용해준다.
    • NUMBER : 숫자가 아닌 부분을 건너띄고 숫자부터 ~ 다시 문자가 나오는 부분까지를 반환
    • TAIL: 나머지 // 이 부분은 문제 풀이에 큰 상관이 없기에 따로 구하지 않아도 된다.
  • HEAD값을 key값으로 하여 Dictionary에 (NUMBER, ORIGINALFILE, index) 를 값으로 저장해준다. // 숫자, 기존 파일명, 들어온 순서

  • 정렬하기

    • HEAD값이 같은 파일명이 존재할 때 → values에 여러 값이 저장되기 때문에 딕셔너리를 key값으로 우선 정렬한 후 value 값을 돌며 조건대로 숫자순, 들어온 순 정렬을 하는 로직

💬 풀이

func solution(_ files:[String]) -> [String] {
    var headNumberDict: [String: [(Int, String, Int)]] = [:] 
    var res: [String] = []
    
    for (index, file) in files.enumerated() {
        let HEAD = file.prefix{ !$0.isNumber }.lowercased()
        let NUMBER = file.drop { !$0.isNumber }.prefix(while: { $0.isNumber })
        
        if headNumberDict[HEAD] != nil {
            headNumberDict[HEAD]?.append((Int(NUMBER) ?? 0, file, index))
        } else {
            headNumberDict[HEAD] = [(Int(NUMBER) ?? 0, file, index)]
        }
    }
    
    for i in headNumberDict.sorted(by: { $0.key < $1.key }) {
        let s = i.value.sorted(by: { $0.0 == $1.0 ? $0.2 < $1.2 : $0.0 < $1.0 })
        for j in s {
            res.append(j.1)
        }
    }

    return res
}

💬 더 나은 방법?

  • 딕셔너리를 사용하고도 sorted(by: )를 사용할 것이면
  • 딕셔너리를 사용하지 않고 배열을 사용하여 한번에 sorted(by: ) 에서 조건을 주어 사용자 지정 정렬을 해줄 수 있다.
    → 2중 for문을 사용하지 않아도 되어 코드도 효율적이고 훨씬 깔끔하다.
func solution(files:[String]) -> [String] {
    var arr: [(String, Int, Int, String)] = []
    var res: [String] = []
    
    for (index, file) in files.enumerated() {
        let HEAD = file.prefix{ !$0.isNumber }.lowercased()
        let NUMBER = file.drop{ !$0.isNumber }.prefix(while: { $0.isNumber }).prefix(5)
        
        arr.append((HEAD, Int(NUMBER) ?? 0, index, file))
    }
    
    arr = arr.sorted(by: {
        if $0.0 != $1.0 { return $0.0 < $1.0 }
        if $0.1 != $1.1 { return $0.1 < $1.1 }
        return $0.2 < $1.2
    })
    
    for i in arr {
        res.append(i.3)
    }

    return res
}

💬 알게된 문법

✅ drop(while:)

주어진 조건자를 건너띈 첫번째 시퀀스부터 반환합니다.

let numbers = [3, 7, 4, -2, 9, -6, 10, 1]
let startingWithNegative = numbers.drop(while: { $0 > 0 })
// startingWithNegative == [-2, 9, -6, 10, 1]

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions