이번엔 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, 3, 23, 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함수 사용법을 잘 기억해서 적재적소에 잘 쓸 수 있어야겠다
'프로그래밍 > Python' 카테고리의 다른 글
[Django] 장고 기초 - (2) Template Language (0) | 2023.04.17 |
---|---|
[Django] 장고 기초 - (1) 개요 및 개발 환경 구성 (0) | 2023.04.14 |
[Python] 자료형 특집 - (1) 시퀀스 타입(List/Tuple/Range) (0) | 2023.03.24 |
[Python] 함수 사용법 - (3) itertools (2) | 2023.03.22 |
[Python] 함수 사용법 - (1) enumerate() (0) | 2023.02.28 |