Comparator, compareTo 이용하는 문제 정리 + 프로그래머스 파일명 정렬

byeol·2023년 4월 20일
0

접근

프로그래머스 [3차] 파일명 정렬
프로그래머스 가장 큰 수
백준 가장 높은 탑 (2655번)
백준 좌표 정렬하기 2 (11651)

오늘 Comparator 문제를 풀었습니다.
풀면서 이 부분을 정리하면 좋겠다는 생각이 들어 정리해보려고 합니다.

Comparator와 Comparable는 모두 인터페이스이고
용도는 비슷하지만 사용하는 방법이 조금 다릅니다.

Comparator의 compare(Object o1, Object o2) 두 개의 매개변수를 통해 매개변수끼리 비교하고 Comparable의 compareTo(Object o) 한 개의 매개변수를 자신과 비교합니다.

둘 중에 하나를 선택해서 정렬할 때 사용하면 됩니다.
저는 Comparator의 compare를 사용하는게 더 익숙해서 정렬을 할 때는 compare()메서드를 오버라이딩해서 진행합니다.

  Comparator<String> comp = new Comparator<String>() {
        
      public int compare(String s1,String s2){
          return s1.length()-s2.length();         
      };

라고 할 때 반환값이 음수와 0인 경우는 들어온 순서를 유지하고 양수인 경우 자리 교환이 일어납니다.

보통 응용해서 문제를 내는데 오늘 푼 파일명 정렬은 추가로 "사전순"이라는 방법을 문제에 넣었습니다.
사전순으로 정렬할 때는 compare() 메서드 안에 compareTo() 메서드를 활용합니다.

"AA".compareTo("BB"); //음수
"BB".compareTo("AA"); //양수
"AA".compareTo("AA"); //0

따라서 오늘 푼 파일명 정렬의 풀이는 아래와 같습니다.

풀이

import java.util.*;
class Solution {
    public String[] solution(String[] files) {
      
    
    //파일 저장소 서버 관리
    //이름 순으로 정렬 나중 만들어진 ver-10이 ver-9보다 먼저 표시
    //숫자를 반영한 정렬기능
    
    //파일명 100글자이내, 영문 대소문자, 숫자, 공백, 마침표, 빼기
    // 영문자 시작, 숫자 하나이상 포함
    
    //Head: 숫자가 아닌 문자 최소 1글자 이상 -> 사전 순 / 대소문자 구분X
    //NUMBEr : 한글자~최대 5글자 앞에 0이 올수 있음 // Head가 같은 경우 -> 숫자 순으로
    //TAIL: 그 나머지 부분, 숫자가 다시 나타거나 아무 글자 없음 -> head,number 같은 경우 원래 입력의 주어진 순서 유지
    
    Comparator<String> comp = new Comparator<String>() {
        
      public int compare(String s1,String s2){
          //Head는 대소문자 구분이 없으므로 
          String newHead1 = checkHead(s1).toLowerCase();
          String newHead2 = checkHead(s2).toLowerCase();
          //Head가 서로 다른경우
          if( newHead1.compareTo(newHead2)!=0){
              //Head는 사전순으로
              return newHead1.compareTo(newHead2); //음수이면 그대로 양수이면 바꾸기
            //Head가 같은 경우
          } else{ 
              // Number 크기 순으로 배열
               return checkNumber(s1) - checkNumber(s2) ;
               
           }        
        }          
      };
              
        Arrays.sort(files,comp);
             
        return files;
    }
    
    //Head를 분리하는 함수
    static String checkHead(String str){
        String answer="";
        
        for(char s : str.toCharArray()){
            //숫자가 등장하면 즉시 멈추기
            if(Character.isDigit(s)) break;
            answer+=s;         
        }    
        return answer;
    }
    
    //Number를 분리하는 함수
    static int checkNumber(String str){
        //checkHead를 통해서 숫자만 남기기
        int length = checkHead(str).length();
        str=str.substring(length);
        
        String sub_answer="";
        
        
        int index=1;
        for(char s : str.toCharArray()){
            //5글자 넘어가는 경우 break;
            if(index>5) break;
            //숫자인 경우 누적
            if(Character.isDigit(s)) sub_answer+=s;
            //영문자가 등장하는 경우 break;
            else break;
            index++;
         }
         //숫자로 바꾸기
         int answer = Integer.parseInt(sub_answer);    
         return answer;
    }
}
profile
꾸준하게 Ready, Set, Go!

0개의 댓글