0404 TIL

looggi·2023년 4월 4일
0

TILs

목록 보기
54/114
post-thumbnail

django

  1. Queryset의 중복을 어떻게 제거할 것인가?
    distinct() 메서드를 사용해서 중복을 제거할 수 있습니다. distinct 메서드를 사용하면 SQL문에 SELECT DISTINCT가 실행됩니다. 이때 ORDER_BY를 함께 사용하게되면 정렬에 사용한 필드가 DISTINCT에 추가되어 원하는 필드에 대해서만 중복제거가 불가능해져 결과적으로 중복 제거가 안된 상태로 리턴이 될 수 있습니다. 따라서 두 메소드를 함께 사용할 땐 주의가 필요합니다.

  2. Django의 기능중 bulk와 관련된 기능들
    여러개의 object에 대한 작업을 수행하는 메소드들을 벌크 메소드라고 합니다.
    bulk_create는 여러개의 object를 생성할 때 사용하며 인자로 obj리스트와 배치사이즈(선택)를 받습니다. obj리스트는 모델(필드=값)의 형태로 입력되며 배치사이즈는 한번에 생성할 객체의 최대 갯수를 지정하고 값을 지정하지 않으면 obj리스트의 모든 객체를 한번에 생성합니다.
    이와 유사하게 bulk_update가 있습니다.
    in_bulk메소드는 필드값과 필드 이름을 인자로 받으며 필드값이 있으면 해당하는 필드이름과 매핑하여 딕셔너리 형태로 리턴해줍니다. 이 때 필드이름은 unique=True여야 합니다.

  3. Django 프로젝트를 배포할 때 사용되는 Gunicorn이 무엇이며, WSGI를 왜 사용해야 하는지 설명하시오

구니콘은 WSGI 중 하나로 웹서버와 장고 사이에서 클라이언트가 보낸 요청을 처리해준다. 장고의 런서버와 같은 역할을 하며 어플리케이션 서버와 함께 있으면 웹어플리케이션 서버의 역할을 해서 동적컨텐츠를 제공할 수 있다.

스터디 문제풀기

12. Integer to Roman

class Solution:
    def intToRoman(self, num: int) -> str:
        ans=''
        roman={1000:'M',500:'D',100:'C',50:'L',10:'X',5:'V',1:'I',}
        for i,k in enumerate(roman.keys()):
            if num//k !=4:
                ans+=(num//k)*roman[k]
            else:
                if ans:
                    if ans[-1]==roman[list(roman.keys())[i-1]]:
                        ans=ans[:-1]
                        ans+=roman[k]+(roman[list(roman.keys())[i-2]])
                    else:
                        ans+=roman[k]+(roman[list(roman.keys())[i-1]])
                else:
                    ans+=roman[k]+(roman[list(roman.keys())[i-1]])
            num=num%k
        return ans

정수를 로마숫자로 바꾸는 문제
로마숫자에 해당하는 숫자는 딕셔너리로 정의해준다. 이후 로직에서 입력받은 숫자 num을 roman의 각 키로 나눠보면서 큰 수부터 제거해나갈 것이므로 딕셔너리를 만들 때 큰 수부터 넣어줬다.
근데 생각해보니 딕셔너리는 순서보장이 되지 않는데 여기서는 roman을 가지고 딱히 뭔가를 한 게 없어서 괜찮은건가..? 아님 파이썬 3부터는 순서를 보장한다는 게 저번엔 거짓말같았는데 리코드에서는 되는건가..?

아무튼 그렇고, 이후에서는 이전에 설명한 것처럼 큰 수부터 제거할 것이기때문에 num을 몫으로 나눈 값만큼 해당 로마숫자가 반복되어 ans에 더해진다.
단 이건 몫이 4가 아닐 때만 해당되는데, 이유는 4,9가 나오면 순서가 바뀌기 때문이다.
4,9에 해당하는 숫자는 해당 몫만큼 자릿수(키)에 해당하는 로마숫자(밸류)를 반복해선 안되고 해당 숫자의 자릿수(키) 직전 키의 밸류값과 해당숫자 자릿수(키)의 밸류값을 역순으로 더해줘야한다.
그래서 해당숫자에 해당하는 로마숫자 +해당숫자+1에 해당하는 숫자를 ans에 더해주는데 해당숫자+1는 index상 하나 앞에 있으므로 그 로마숫자를 찾기 위해서 i-1의 값을 인덱싱해서 더해준다
첫번째 if문은 ans가 비어있을 때에 나는 인덱스 에러를 막기 위한 것이고(4로 시작하는 숫자) 두번째 if는 4와 9 를 구분하기 위한 것이다. 9는 5+4라서 5에해당하는 숫자와 4에 해당하는 숫자가 더해질 수 있기때문에 구분이 필요하다. 5 이후에 4가 나오는 경우는 5에 해당하는 로마숫자를 ans에서 지워주고 9에 해당하는 숫자를 더해준다.
num에는 몫을 제외한 나머지가 들어가서 다음 for문을 실행한다.

정리하면서 생각해보니 첫번째 자리부터 돌면 어떨까 싶기도 하고 아니면 애초에 딕셔너리에 4,9에 해당하는 숫자들을 다 넣었으면 어떨까 싶기도 한데 그래도 뭔가 한번에 처리하는 로직을 만든다는 데에 목표가 있었으니까 .. 리팩토링을 해봐야겠다

class Solution:
    def intToRoman(self, num: int) -> str:
        ans=''
        roman={1000:'M',500:'D',100:'C',50:'L',10:'X',5:'V',1:'I',}
        roman_keys=list(roman.keys())
        for i,k in enumerate(roman_keys):
            if num//k !=4:
                ans+=(num//k)*roman[k]
            else:
                if ans and ans[-1]==roman[roman_keys[i-1]]:
                    ans=ans[:-1]
                    ans+=roman[k]+(roman[roman_keys[i-2]])
                else:
                    ans+=roman[k]+(roman[roman_keys[i-1]])
            num=num%k
        return ans

중복되는 코드를 없애고 중복계산되는 부분이 많아서 아예 변수에 넣어줬다. 끝!

profile
looooggi

0개의 댓글