프로그래밍/Python

[Python] 함수 사용법 - (2) sort(), sorted()

Churnobyl 2023. 3. 19. 22:18
728x90
반응형

 

이번엔 sort(), sorted()의 차이점과 익명함수(Anonymous Function) lambda에 대해서 알아보자

def solution(numlist, n):
    answer = sorted(numlist,key = lambda x : (abs(x-n), n-x))
    return answer
    
solution([1, 2, 3, 4, 5, 6], 4)
solution([10000,20,36,47,40,6,10,7000], 30)

문제: solution(m_list, n)에서 n에 가장 가까운 값부터 차례로 정렬하는 문제이다. 만약 거리가 같다면 더 큰 수를 앞에 오도록 배치한다

 

위 풀이는 sorted()함수의 optional parameter인 key를 이용해 간단하게 문제를 해결했다

 


sorted(iterable, [key=function or callable], [reverse=True or False])

iterable한 객체를 순차적으로 나열(정렬)한다

 

  • iterable: member를 하나씩 차례로 반환 가능한 객체
  • Optional Parameter
    • key : 정렬의 기준이 되는 함수 또는 튜플, 리스트 등의 callable 객체(정확히 말하면 class내에 __call__메서드가 있는 객체). 기본값 None
    • reverse: 오름차순/내림차순을 bool값으로 결정. 기본값 False(오름차순)

아래의 예제를 보자

 

lotto_number = [23,43,3,12,6,8]

# 1
print(sorted(lotto_number))

# 2
print(sorted(lotto_number, reverse=True))

# 3
print(sorted(lotto_number, key=lambda x: str(x)[-1]))

# 4
print(sorted(lotto_number, key=lambda x: (str(x)[-1], str(x)[0]), reverse=True))
[3, 6, 8, 12, 23, 43]
[43, 23, 12, 8, 6, 3]
[12, 23, 43, 3, 6, 8]
[8, 6, 43, 3, 23, 12]

 

# 1

lotto_number가 오름차순으로 출력됐다

 

# 2

lotto_number가 내림차순으로 출력됐다

 

# 3

lotto_number의 요소 중 1의 자리수를 기준으로 낮은 값부터 출력이 되었다. 값이 같을 경우(23, 43, 3) 기존 리스트의 순서로 출력됐다.  [12, 23, 43, 3, 6, 8]

 

# 4

함수가 두개 이상의 정렬 기준을 가지고 있는 경우(multiple levels of sorting)에도 잘 작동한다. 위와 같은 경우는 #3과 같이 정렬 후 각 요소의 첫번째 값이 가장 큰 요소부터 정렬됐다. [8, 6, 43, 323, 12]

 

 

위는 iterable한 객체 중 많이 사용되는 list에 대한 사용법이었다

이제 다른 iterable한 객체에 대해 사용해보자

 

shopping_list = {
    'egg': 3,
    'bacon': 7,
    'olive oil': 2,
    'kimchi': 4
}

# 1
print(sorted(shopping_list))

# 2
print(sorted(shopping_list.values()))

# 3
print(sorted(shopping_list.items()))


class MustGo:
    def __init__(self, name, star, reviews) -> None:
        self.name = name
        self.star = star
        self.reviews = reviews
    def __repr__(self) -> str:
        return repr((self.name, self.star, self.reviews))
    
mustgo_restaurants = [
    MustGo('John\'s Pizza', 4, 27),
    MustGo('Chef Gon', 4.5, 13),
    MustGo('BongPiYang', 3.6, 54),
    MustGo('Rokka', 4.5, 45)
]

# 4
print(sorted(mustgo_restaurants, key= lambda x: x.star))

# 5
print(sorted(mustgo_restaurants, key= lambda x: (x.star, x.reviews), reverse=True))
['bacon', 'egg', 'kimchi', 'olive oil']
[2, 3, 4, 7]
[('bacon', 7), ('egg', 3), ('kimchi', 4), ('olive oil', 2)]
[('BongPiYang', 3.6, 54), ("John's Pizza", 4, 27), ('Chef Gon', 4.5, 13), ('Rokka', 4.5, 45)]
[('Rokka', 4.5, 45), ('Chef Gon', 4.5, 13), ("John's Pizza", 4, 27), ('BongPiYang', 3.6, 54)]

#1, #2, #3은 딕셔너리에 대한 예제이며 #4, #5는 __repr__메소드의 리턴값으로 튜플을 가진 맛집(MustGo) 리스트에 대한 사용 예시이다

 

# 1

key값을 기준으로 문자열이 오름차순 정렬됐다

 

# 2

value값을 기준으로 오름차순 정렬됐다

 

# 3

key값을 기준으로 정렬된 key, value쌍이 출력됐다

 

# 4

MustGo클래스의 star필드를 기준으로 오름차순 정렬됐다

 

# 5

Mustgo클래스의 star필드와 reviews필드를 기준으로 내림차순 정렬됐다

 

이처럼 sorted() 함수의 key 파라미터는 이름을 가진 속성(attributes)도 받을 수 있다

 


sort([key=function or callable], [reverse=True or False])

List를 순차적으로 나열(정렬)한다

 

  • sort()함수는 sorted()함수와 달리 list객체에만 사용할 수 있다
  • 해당되는 list 자체의 값을 정렬한다
  • Optional Parameter
    • key : 정렬의 기준이 되는 함수 또는 튜플리스트 등의 callable 객체(정확히 말하면 class내에 __call__메서드가 있는 객체). 기본값 None
    • reverse: 오름차순/내림차순을 bool값으로 결정. 기본값 False(오름차순)

아래의 예제를 보자

 

lotto_number = [23,43,3,12,6,8]

# 1
sort(lotto_number)

# 2
print(lotto_number.sort())

# 3
lotto_number.sort()
print(lotto_number)

# 4
shopping_list = {
    'egg': 3,
    'bacon': 7,
    'olive oil': 2,
    'kimchi': 4
}

shopping_list.sort()
NameError: name 'sort' is not defined
None
[3, 6, 8, 12, 23, 43]
AttributeError: 'dict' object has no attribute 'sort'

 

# 1

sort()함수는 [list].sort() 형태로 사용되므로 NameError를 반환했다

 

# 2

sort()는 list자체를 수정하고 혼란을 방지하기 위해 None을 리턴한다

 

# 3

정상적으로 오름차순 정렬됐다

 

# 4

딕셔너리 객체에는 sort()속성이 없으므로 AttributeError를 반환했다

 

 


lambda [parameter list] : <expression>

람다함수. 이름없는 함수(익명함수)를 만드는 데 사용된다. lambda로 만들어진 함수는 일반 함수와 똑같이 동작한다

add_ten = lambda x: x+10
print(add_ten(10))
20

위의 표현처럼 사용해 이름 없는 함수에 이름을 만들어 줄 수도 있고 주로 함수를 매개변수로 받는 함수에 사용한다

 

 


코드풀이

이제 코드를 하나씩 뜯어보자

전체코드

def solution(numlist, n):
    answer = sorted(numlist,key = lambda x : (abs(x-n), n-x))  # 1
    return answer
    
solution([1, 2, 3, 4, 5, 6], 4)
solution([10000,20,36,47,40,6,10,7000], 30)

 

# 1 

abs(x-n)이 첫번째 조건이고 n-x가 두번째 조건이다

x-n의 절댓값 순으로 numlist를 오름차순 정렬하는데, x-n의 절댓값의 크기가 같다면 부호를 바꿔 n-x가 작은값(즉, x가 큰값)으로 정렬을 하겠다는 뜻이다

따라서 위 코드는 아래와 같이 출력된다

 

[4, 5, 3, 6, 2, 1]
[36, 40, 20, 47, 10, 6, 7000, 10000]

 


생각

이번 문제는 어렵게 생각하면 어렵고 정렬의 조건문을 잘 설정하면 쉽게 풀 수도 있는 문제였다나는 어렵게 풀었지만 lambda함수 사용법을 잘 기억해서 적재적소에 잘 쓸 수 있어야겠다

반응형