ASAC 빅데이터 분석가 7기/ASAC 일일 기록

ASAC 빅데이터 분석가 과정 5일차 - 2 (24.12.10)

junslee 2024. 12. 10. 15:05

06_정렬_파일이름

# ref)
문제 : https://programmers.co.kr/learn/courses/30/lessons/17686?language=python3
정규식 참고 : https://painted-starfish-9d5.notion.site/1582b2da920780e3a228e91a1592c5fc

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

참고) 정규식 | Notion

정규식은 텍스트 문자열을 어떠한 패턴으로 파악하여 식별하는데 사용이 된다. → 내가 지정한 규칙에 해당하는지, 해당하지 않는지에 대해서 알려주게 된다.

painted-starfish-9d5.notion.site

# 참고 : 정규식!!!! ==> 문자열에 대한 패턴/ 규칙 표현!!!!!
---> gpt를 이용하시면 편하지 않을까...
     : 카카오 계열사의 특징 중 하나 종종 정규식
     : 일반적인 부분에서는 자주 나오지는 않음;;;

 

//리스트랑 dict를 모두 연습하자


문제 상황을 체크!!!
기존의 정렬 방식 : 글자별로 코드값을 기준으로 하나씩 정렬!!!!
                   img10.png, img2.png
                   ==> img2.png, img10.png( 숫자크기가 대소 반영!!!)

파일명 : 영문대/소, 숫자, 공백, 마침표, 빼기기호
         최대 길이가 100글자
       : 제약조건 ==> 시작은 영문자(대/소)
                        ==> 숫자는 무조건 1개 이상!!!

파일명의 구성 : 3가지 파트로 구성
head : 처음부터~~~ 처음숫자가 나타나기 전까지 부분!!!!!
number : 처음 숫자 덩어리파트 (+++ 0010 제로 패딩!!!!)
tail : 그 외.....


위의 3가지 파트를 기준으로 정렬!!!
정렬기준1) head 파트 & 사전순(오름차순)
           단, 대/소문자 구별X ==> 통일이 필요할 것!!(대 or 소)
정렬기준2) number파트 & 숫자크기(오름차순)
           단, zero padding 앞 처리 --> 00010 : 10
정렬기준3) 원본의 순서를 유지해주세요!!!
---> tail부분은 정렬에 사용하지 않네;;;;
---> tail은 굳이 처리를 안 해도 되지않을까;;;;
단,,,,,원본의 순서!!!!!!!


주관적인 결론!!!)
정렬에 대한 필요한 정보 (head, number, 원본순서)
+ 최종 출력 : 원본 파일명
==> ( 원본파일명, head, number, 원본순서)


샘플 케이스 분석

# 예제1
입력 :["img12.png", "img10.png", "img02.png", "img1.png", "IMG01.GIF", "img2.JPG"]
==> 출력: ["img1.png", "IMG01.GIF", "img02.png", "img2.JPG", "img10.png", "img12.png"]

1) 필요한 정보를 추출 : head, number, 원본순서
"img12.png"   : img,  12, 0    (6)
"img10.png"   : img,  10, 1    (5)
"img02.png"   :  img, 02, 2    (3)
"img1.png"     : img,  1,   3    (1)
"IMG01.GIF" : IMG, 01, 4    (2)
"img2.JPG"    : img,   2,  5    (4)
==> 출력 양식 : 내가 정리한 정보 스타일X
                         입력으로 받은 원본 파일명으로 그대로 출력!
==> 리스트로 구현을 할 것인가,,,dict로 할 것인가...선택!!!!!

 

# 예제2
입력: ["F-5 Freedom Fighter", "B-50 Superfortress", "A-10 Thunderbolt II", "F-14 Tomcat"]
-->출력: ["A-10 Thunderbolt II", "B-50 Superfortress", "F-5 Freedom Fighter", "F-14 Tomcat"]
F-5 Freedom Fighter : (F-, 5, 0)       (3)
B-50 Superfortress  : (B-, 50,1)       (2)
A-10 Thunderbolt II : (A-, 10,2)       (1)
F-14 Tomcat         : (F-, 14, 3)      (4)


정렬을 하기 위한 필요한 정보들을 추출하는 과정에서.. 규칙!!!!
==> 기준 : 파일명 속에서 처음 나타나는 숫자!!!!( 숫자 1~5글자,0~9, 제로패딩)
    기준앞 : head
    기준 : number
==> 문자열에 대한 규칙화 문법 : 정규식!!!!
    파이썬의 잡다한 문자열에 대한 기능(메서드) / 리스트      //정규식과 메서드 공부하자!!


사전 지식 1) 정규식!!!!!
목적 : 문자열 내에서 내가 원하는 패턴을 찾는 룰(규칙!!!)
---> 일반적인 모든 언어들에 대해서 다 존재를 함!!!!
       큰 틀에서는 거의 유사함!!!조금 언어별로 차이가 있는 구문이 있을 수 있음!!!
---> 파이썬 : re패키지 (코테 플랫폼 : 기본으로 사용할 수 있는 패키지!!!)     //re 정규식 정리하기!!

import re
==> anaconda 패키지 버전에서도 기본으로 설치가 되는 패키지!!!
       colab에서도 기본적으로 설치가 되어 있음!!!!
==> 필요하면, 불러오기만 하면 됨!!!!!!!

 

// https://proximal-stranger-fa0.notion.site/re-cd9966fe6c3b4756acf72df084910b51

 

re 정규표현식 | Notion

1. 정규 표현식 문법과 모듈 함수

proximal-stranger-fa0.notion.site

#정규식의 규칙으로 작성된 문자열 vs 쌩파이썬의 문자열!!!!
"hello. 100$" # -- 일반적인 문자열
r"hello. 100$" # -- 일반적인 문자열 앞에서  r
--> 일반 문자열이 아니라 정규식으로 작성된 문자열!!!!!

==> .()\[]*+ 기호들이 일반적인 특수문자 기호가 아니라....
    정규식 패키지가 사전에 정의해놓은 규칙을 표현하는 문자!!!!!!!

#정규식 기본 틀
* vs + : 원하는 패턴0번 이상 vs 원하는 패턴1번 이상 ==> 출현 빈도
[문자들] : 여러개들 중에서 하나라도,,,,,==> [Pp]ython
. : 줄바꿈을 제외하고 뭐라도 1개 문자/공백 
{n} : 패턴의 반복을 지정!!!!!

 

[0123456789] # 0~9까지 숫자 중 하나 체크!!!!
[0-9]
\d # 편하기는 하지만,,,,구체적으로 컨트롤을 할 수 없음!!!!
---> 하나만 알면 되지 않을까요???? No!!!!
예) 주민번호 XXXXXX - [1234]XXXXXX
                     XXXXXX - [1-4]XXXXXXX

# 정규식을 특정 패턴에 대해서 찾을 때 ===> findall
re.findall( 패턴-->규칙(정규식룰), 어디서)

temp ="SSdsdsdsdsd1w32fdfdfadfadf1343434****343sdasxdqrsf.fdfppdfdf134ff"
temp

ex) 찾을 규칙 : 숫자1개로 이루어진 것들을 다 찾아주세요!!!!
re.findall( r"\d", temp)

ex) 찾을 규칙 : 숫자1개 이상으로 연결된 것들은 다 찾아줘!!!
re.findall( r"\d+", temp)

re.findall( r"\d*", temp)
===> 꼭!!! 제대로 원하는 패턴이 잘 찾아지는제 테스트를 꼭 하세요!!!

re.findall( r"[0123456789]+",temp)

re.findall( r"[0-9]+",temp)

re.findall( r"[3-4]+",temp)

re.findall( r"[a-z]+",temp) # 소문자 1개 이상 연속된 패턴!!!!

re.findall( r"[A-Z]+",temp) # 대문자 1개 이상 연속된 패턴!!!!

 

[a-zA-Z] : 대소문자 다 가능!!!!
[A-z]    : 대소문자 다 가능!!!!
==> [a-Z] : 에러가 발생을 하는 정규식!!!
re.findall( r"[A-Z]+",temp)


# 사전지식2) 숫자 앞에 붙은 0을 어찌처리할까요????
===> 정렬을 하기 위해서는 0이 제거된 숫자가 필요함!!!
"000023" ---> 숫자 23

[1-9]+ : 203 xXXXXXXX

int("00023")

str( int("00023"))


# 사전 지식 1&2적용 : temp문자열에서 한 번 처리를 해보죠!!!
temp ="SSdsdsdsdsd032fdf2dfa9dfadf134300434****00343sdasxdqrsf.fdfppdfdf1034ff"
temp

re.findall(r"\d+", temp)

re.findall(r"\d+", temp)[0] # --> number파트 추출!!!!!

[ 1,3,3,3,4,2,3,3,5].index(4)

"aasdsdsdsdsdsds".index("d")

temp.index(re.findall(r"\d+", temp)[0] )      //number 파트 구현

temp[:temp.index(re.findall(r"\d+", temp)[0] )]      //number 파트 재활용
# ---> head파트....


# 사전지식3) 문자열 --> 정렬을 대소문자 동일하게 간주!!!!
===> 문자열에서 대소문자에 대한 일괄변환!!!!
"AAAssdsdFD".lower()

"AAAssdsdFD".upper()


방법1) 리스트를 사용해서 체크!!!!!
  ---> (head:소문자, number:숫자, 원본위치)
  ---> (head, numner, 원본위치, 원본파일명) [ 개인적으로 한 번 해보세요!!!]

방법2) dict 사용해서 체크!!!!!!!!!
  --> k : 파일명(중복된 파일명이 없음!!!!!)
       v : (h, n, idx)


# Try1) 리스트 --> (h, n, idx)

import re

 

def solution(files):

    answer = []

    ##

    # 0. 기본적인 세팅 : 정렬에 필요한 정보를 담을 변수 : 리스트

    #    --> (head : 소문자, number : 숫자, 원본위치)

    my_files = [] # [(h,n,i), (h,n,i), ...]

    # 1. 돌리는 큰 틀 : 입력의 files 리스트를 다 돌리면...

                  ==> 원하는 정보를 추출, my_files에 담으면 됨!!

                  ++ 원본위치 : 입력 파일리스트의 정수 인덱스

    for idx, s in enumerate(files) :

        # s 개별 파일명 --> h, n 정보 추출!!

        # 1-1) 기준 : 가장 처음에 나타나는 숫자 덩어리 ==> 정규식!!

        number = re.findall( r"\d+",s) # s:foo010bar020.zip --> [ "010", "020"]

        # 이 중에서 가장 처음 나타난 숫자 덩어리 + 숫자화!!

        real_number = int(numbers [0]) # "010" --> int --> 10

        # ==> number 파트 정리 끝!

        # 1-2) head 파트 추출 : 처음~~ 숫자파트 시작 전

        head = s[:s.index(numbers[0])] # Foo

        head = head.lower()                  # Foo --> foo

 

        # 1-3) 필요한 정보를 모으자!!

        # ["foo", 10, 0], ["img",3,1] ,...]

        my_files.append([ head  , real_number  , idx ])

    # --> 입력으로 받은 files들을 다 처리르 하면 됨!!

 

    # 2) 문제에서 주어진 조건대로 정렬!!!

    #    + 일반적인 조건이 아니라 주어진 대로 내가 직접 작성!!

    #     .sort(), sorted() + key + lambda + (+/-)

    #  ==> 원본에 대한 파일명 : files에 아직 그대로 존재!!

    my_files.sort( key = lambda x: (x[0], x[1], x[2]) )

    # [["img",3,1], ["zmgoo", 10, 0],...]

 

    # 3) 최종 제출 스타일로 정리!! --> 원본 파일명!!

    # for j in my_files: # ["aaa", 10, 3]:

    #     answer.append(files[j[2]])

    answer = [files[ j[2]] for j in my_files]

 

    return answer


# Try2) Dict

==> my_files = {}

        k : 중복이 없는 원본 파일명 --> 문제에서 중복 없다고 해서..

        v : 정렬에 필요한 정보 (head, number, org_idx)

==> 정렬을 기준이 어디에?? --> 오로지 value에 존재!!

        my_files.items(), my_files.values() etc...

 

import re

 

def solution(files):

    answer = []

    # 세팅

    my_files = {} # k : 파일명, v : (h,n,idx)

    #개별 파일들을 돌아가서

    for idx, s in enumerate( files ):

        p = re.findall(r"\d+", s) [0]

        head = s[:s.index(p)].lower()

        number = int(p)

        my_files[s] = (head, number, idx)

        # {"aA010.jpg" : (aa, 10, 0), "bddA23.jof" :("bdda",23,1),...}

    # ----> 정렬 !!

    file_list = my_files.items()

    # [ ( "bddA23.jof" ,("bdda",23,1) ), (  {"aA010.jpg" ,(aa, 10, 0) ) ]

    file_list = sorted(file_list, key = lambda x : (x[1][0], x[1][1], x[1][2]))

    # [(  {"aA010.jpg" ,(aa, 10, 0) ), ( "bddA23.jof" ,("bdda",23,1) )]

    answer = [i[0] for i in file_list]

    return answer


# test1
a = ["img12.png", "img10.png", "img02.png", "img1.png", "IMG01.GIF", "img2.JPG"]
solution(a)
#입력: ["img12.png", "img10.png", "img02.png", "img1.png", "IMG01.GIF", "img2.JPG"]
#출력: ["img1.png", "IMG01.GIF", "img02.png", "img2.JPG", "img10.png", "img12.png"]

# test2
a = ["F-5 Freedom Fighter", "B-50 Superfortress", "A-10 Thunderbolt II", "F-14 Tomcat"]
solution(a)
#입력: ["F-5 Freedom Fighter", "B-50 Superfortress", "A-10 Thunderbolt II", "F-14 Tomcat"]
#출력: ["A-10 Thunderbolt II", "B-50 Superfortress", "F-5 Freedom Fighter", "F-14 Tomcat"]


 

 

*** 오늘 했던 것들은 

--> 이해를 하시고,,

본인 스타일로 정리

--> 연습을 통해서 손이 움직일 수 있도록 연습!!

 

*** 내일은 기본적인 내용 살짝 정리하고 --> 

정렬 알고리즘 & 탐색 알고리즘!!

*** 꼭 !! 스스로 정리하세요!!