students.sort(key=lambda x: (-x.native_lang, x.english, -x.math, x.name))
객체 리스트 정렬 방법에 관한 정보만을 바로 보려면 아래 3번 문단으로
클래스로 찍어낸 객체들을 배열한 리스트에서,
객체의 여러 속성을 기준 삼아 정렬하는 알고리즘을 익히기 좋은 문제가 있어 정리.
(물론 문제만 해결하자면 객체를 만들지 않고 2차원 배열을 이용하는 방법이 더 간단하다)
https://www.acmicpc.net/problem/10825
1. 객체를 담을 클래스는 다음과 같다
class Student:
def __init__(self, name, native_lang, english, math):
self.name = name
self.native_lang = native_lang
self.english = english
self.math = math
def __repr__(self):
return repr((self.name, self.native_lang, self.english, self.math))
클래스 이름 : Student
__init__ 생성자를 통해 이름(name)과 국어(native_lang), 영어(english), 수학(math)의 점수 value를 저장할 필드를 만든다.
__repr__() 함수는 객체 확인을 위해 편의상 작성.
2. 입력 값을 받아 객체를 생성하고 리스트에 담는다.
num = int(sys.stdin.readline())
students = []
for _ in range(num):
input_list = list(map(str, sys.stdin.readline().split()))
stu_1 = Student(input_list[0], int(input_list[1]), int(input_list[2]), int(input_list[3]))
students.append(stu_1)
객체를 담을 객체 리스트의 이름은 students이다.
입력 케이스(num) 만큼 반복문을 돌며 stu_1 이란 객체를 생성하고 리스트에 추가한다.
3. 객체 리스트의 정렬
students.sort(key=lambda x: (-x.native_lang, x.english, -x.math, x.name))
파이썬의 sort 함수에는 key 값을 함수 인자로 받아 정렬 기준을 정할 수 있다.
x 는 람다식의 변수로 다른 이름으로 선언하여 사용해도 된다.
x: 다음에 오는 () 안의 코드가 정렬 기준과 순서이다.
부호는 오름차순/내림차순을 결정한다. -가 내림차순이다.
앞쪽에 위치한 필드가 우선 정렬 기준이 된다.
국어(native_lang)를 기준으로 내림차순 정렬을 한다.
만약 국어 점수의 값이 같을 경우 다음 기준 영어(english)로 넘어간다.
반드시 모든 필드를 key 값으로 넣을 필요는 없다.
한 가지 key값을 넣어도 동작한다.
그러나 key 값을 넣지 않을 경우. sort() 코드에서 TypeError 가 발생한다.
정렬하는 리스트가 다중 필드를 가지고 있어 비교할 기준이 없기 때문이다.
students.sort()
TypeError: '<' not supported between instances of 'Student' and 'Student'
4. 응용
동일한 방법으로 객체 배열뿐 아니라 튜플 리스트, 딕셔너리, 2차원 배열도 원하는 기준으로 정렬이 가능하다.
coordinate = []
for i in range(0, num):
x, y = sys.stdin.readline().split()
coordinate.append((int(x), int(y)))
coordinate.sort(key=lambda sort: (sort[1], sort[0]))
for i in coordinate:
print(i[0], i[1])
x, y 좌표를 튜플 형태로 입력받은 후
y 축 오름차순 우선 정렬하고
y축 좌표가 같을 경우 x축 오름차순으로 정렬하는 코드이다.
람다식의 키값은 서브스트링 문법으로 접근한다.
튜플의 형태가 (x, y) 이기 때문에 s[1] 은 y를, s[0] 는 x를 의미한다.
만약 튜플이 (x, y, z)이고 x, y, z 순서로 정렬하고 싶다면
s[0], s[1], s[2] 순으로 key 값을 입력하면 된다.
딕셔너리의 정렬도 똑같다.
딕셔너리의 key (주의: 람다식의 key 아님)는 s[0], value는 s[1] 으로 지정한다.
# 딕셔너리의 value를 기준으로 정렬
dic.sort(key=lambda s: s[1])
5. 정리
자바에서의 comparable나 comparator를 이용한 정렬과 유사한 방법이다.
아이디어는 같지만 표현하는 문법이 크게 다르다.
자바의 형식미와 파이썬의 단순미.
언어가 추구하는 철학을 잘 보여주는 예시라고 생각한다. 꽤 재밌는 포인트.
그리고 사실 나는 파이썬의 문법이 더 좋다.
(백준 10825번의 전체 코드)
# 백준 q10825
import sys
class Student:
def __init__(self, name, native_lang, english, math):
self.name = name
self.native_lang = native_lang
self.english = english
self.math = math
def __repr__(self):
return repr((self.name, self.native_lang, self.english, self.math))
num = int(sys.stdin.readline())
students = []
for _ in range(num):
input_list = list(map(str, sys.stdin.readline().split()))
stu_1 = Student(input_list[0], int(input_list[1]), int(input_list[2]), int(input_list[3]))
students.append(stu_1)
students.sort(key=lambda x: (-x.native_lang, x.english, -x.math, x.name))
for i in students:
print(i.name)
'기술 기록 > Python,Django' 카테고리의 다른 글
error, 파이참버그) ValueError: invalid literal for int() with base 10: '' / 파이참 인풋 버그 (0) | 2022.05.30 |
---|---|
Django ) 데코레이터를 이용한 유저 검증 (0) | 2022.05.16 |
파이썬PS) 백준 6603 로또. 백트래킹 (0) | 2022.04.12 |
파이썬PS) 백준 7568 덩치 (0) | 2022.03.29 |
python ) 문자열 파싱 (0) | 2022.02.20 |
댓글