[Python] 객체 정렬 - 클래스, 튜플 객체 정렬. lambda. 오름차순. 내림차순. 문자열 사전순

2023. 2. 11. 21:39파이썬(Python)

1. 클래스를 이용한 객체 정렬

● 국어, 수학, 영어 점수를 포함한 학생 정보가 주어졌을 때, 국어 점수를 기준으로 오름차순 정렬을 하기

- key라는 인자에 정렬 기준을 정의해 주는 함수를 넘겨줘야 한다.

- 국어 점수 오름차순이라는 간단한 정렬 기준인 경우 익명 함수 lambda를 사용한다.

- lambda는 이름 없이 사용할 수 있는 함수이다.

 

● 예를 들어 값에 2배를 하여 반환하는 함수는 다음과 같다.

def f(x):
    return x*2

print(f(5))

 

결과

10

 

- 이를 lambda를 이용해 작성하면 다음과 같다.

f=lambda x:x*2
print(f(5))

 

결과

10

 

- 위와 같이 인자 값이 하나인 경우 lambda 뒤에 x를 적어 주고, : 뒤반환한 값을 적어준다.


여기서 잠깐! lambda를 이용한 객체 정렬에 앞서 일반적인 lambda 정렬에 대해 먼저 알아보자.

 

◆ lambda 정렬

a=[1,2,3,4,5,6,7,8,9]
a.sort(key=lambda x:x%2)
print(a)

 

- 위의 코드에서 x는 리스트 a의 원소이고, lambda의 반환 값은 x%2이다.

- a에 따른 반환 값은 다음과 같다

[1,0,1,0,1,0,1,0,1,0]

 

- 따라서 반환 값을 기준으로 오름차순 정렬을 하면 다음과 같다.

[0,0,0,0,1,1,1,1,1]
# 이에 따른 a의 원소는 [2,4,6,8,1,3,5,7,9]

 

결과

[2, 4, 6, 8, 1, 3, 5, 7, 9]

 

 

- 위와 같이 lambda를 사용하면 반환 값을 기준으로 정렬을 하게 된다.

 


a=[1,2,3,4,5,6,7,8,9]
a.sort(key=lambda x:-x)
print(a)

 

- 코드의 반환 값은 -x이므로 반환 값을 정렬하면 다음과 같다.

[-9, -8, -7, -6, -5, -4, -3, -2, -1]

 

- 따라서 반환 값을 기준으로 정렬하여 a를 출력하면 다음과 같다.

[9, 8, 7, 6, 5, 4, 3, 2, 1]

 

- 이처럼 내림차순으로 정렬하려면 주로 반환 값에 -를 붙인다.

 


a=[1,2,3,4,5,6,7,8,9]
a.sort(key=lambda x:x%2==0)
print(a)

 

- 이번엔 반환 조건에 x%2==0이라 하면 어떻게 될까?

- 반환 조건이 x%2일 때와 비교를 해보자.

 

x=3
y=4
print(x%2==1)
print(y%2==1)

 

결과

True
False

 

- 위의 코드처럼 어떤 수를 2로 나눠 나머지가 1일 때, 즉 홀수가 맞는지 판단하는 코드이다.

- 답은 True 또는 False가 나올 것이다.

 

- 그럼 False와 True를 비교하여 어떤 것이 클까?

print(True>False)
print(True==False)
print(True<False)

 

결과

True
False
False

 

- 실제로 비교하면 True가 False보다 크다는 것을 알 수 있다.

- 따라서 반환 값인 x%2==0이 False, 즉 x가 홀수인 값을 먼저 정렬해야 한다.

a=[1,2,3,4,5,6,7,8,9]
a.sort(key=lambda x:x%2==0)
print(a)

# [1, 3, 5, 7, 9, 2, 4, 6, 8]

 


- 그럼 본격적으로 객체 정렬을 알아보자.

- 국어 점수를 기준으로 오름차순으로 정렬해 보자.

- 클래스를 정의하고 5명의 학생들의 국어, 수학, 영어 점수를 입력한 후 학생들의 성적을 출력한다.

 

class Student:
    def __init__(self,kor,math,eng):
        self.kor=kor
        self.math=math
        self.eng=eng

input_data=[tuple(input().split()) for _ in range(5)]
students=[Student(int(kor),int(math),int(eng)) for kor, math, eng in input_data]
print()
for student in students:
    print(student.kor,student.math,student.eng)

 

결과

>> 30 50 60
>> 70 60 90
>> 30 40 70
>> 20 60 40
>> 90 60 50

30 50 60
70 60 90
30 40 70
20 60 40
90 60 50

 

students.sort(key=lambda x:x.kor)

 

- x는 students 리스트의 원소인 Student(kor, math, eng) 객체이다.

- x.kor은 학생의 국어성적이므로 국어 성적을 기준으로 오름차순 정렬을 하게 된다.

 

class Student:
    def __init__(self,kor,math,eng):
        self.kor=kor
        self.math=math
        self.eng=eng

input_data=[tuple(input().split()) for _ in range(5)]
students=[Student(int(kor),int(math),int(eng)) for kor, math, eng in input_data]
print()
for student in students:
    print(student.kor,student.math,student.eng)
print()
students.sort(key=lambda x:x.kor)
for student in students:
    print(student.kor,student.math,student.eng)

 

결과

30 50 60
70 60 90
30 40 70
20 60 40
90 60 50

# 정렬 전
30 50 60
70 60 90
30 40 70
20 60 40
90 60 50

# 정렬 후
20 60 40
30 50 60
30 40 70
70 60 90
90 60 50

 

- 이번엔 수학 점수를 기준으로 내림차순으로 정렬을 해보자

class Student:
    def __init__(self,kor,math,eng):
        self.kor=kor
        self.math=math
        self.eng=eng

input_data=[tuple(input().split()) for _ in range(5)]
students=[Student(int(kor),int(math),int(eng)) for kor, math, eng in input_data]
print()
for student in students:
    print(student.kor,student.math,student.eng)
print()
students.sort(key=lambda x: -x.math)
for student in students:
    print(student.kor,student.math,student.eng)

 

- 내림차순이므로 기준이 되는 수학점수인 x.math-를 붙여 해결한다.

 

30 50 60
70 60 90
30 40 70
20 60 40
90 60 50

# 정렬 전
30 50 60
70 60 90
30 40 70
20 60 40
90 60 50

# 정렬 후
70 60 90
20 60 40
90 60 50
30 50 60
30 40 70

 


2. 튜플을 이용한 객체 정렬

- sort, lambda를 이용한다.

- 이때, lamda에 x값은 국어, 수학, 영어 성적인 tuple 형태이다.

- 국어 점수는 tuple의 0번째 index기 때문에 국어 성적을 기준으로 오름차순 정렬을 하면 x [0]을 반환 값으로 적는다.

- 또한 수학 점수는 tuple의 1번째 index기 때문에 수학 성적을 기준으로 내림차순 정렬을 하면 -x [1]을 반환 값으로 적는다.

 

input_data=[tuple(input().split()) for _ in range(5)]
students=[(int(kor),int(math),int(eng)) for kor, math, eng in input_data]

print()
for kor,math,eng in students:
    print(kor, math, eng)

print()
students.sort(key=lambda x: x[0])
for kor,math,eng in students:
    print(kor, math, eng)

print()
students.sort(key=lambda x: -x[1])
for kor,math,eng in students:
    print(kor, math, eng)

 

결과

30 50 60
70 60 90
30 40 70
20 60 40
90 60 50

# 정렬 전
30 50 60
70 60 90
30 40 70
20 60 40
90 60 50

# 국어 성적 기준
20 60 40
30 50 60
30 40 70
70 60 90
90 60 50

# 수학 성적 기준 내림차순
20 60 40
70 60 90
90 60 50
30 50 60
30 40 70

 


3. 문자열 기준 객체 정렬

- sort와 lambda를 사용한다.

- x인자가 튜플일 때 x [k]가 문자열이면 반환 값을 x [k]라 하면 사전순으로 정렬된다.

input_data=[tuple(input().split()) for _ in range(5)]
students=[(int(kor),int(math),int(eng),name) for kor, math, eng, name in input_data]

print()
students.sort(key=lambda x: x[3])
for kor,math,eng,name in students:
    print(kor, math, eng,name)

 

결과

>> 30 50 60 john 
>> 70 60 90 tom 
>> 30 40 70 max
>> 20 60 40 jane
>> 90 60 50 beo

90 60 50 beo
20 60 40 jane
30 50 60 john
30 40 70 max
70 60 90 tom

 

- 반면, 내림차순으로 하기 위해 반환 값에 -를 붙이면 오류가 난다.

input_data=[tuple(input().split()) for _ in range(5)]
students=[(int(kor),int(math),int(eng),name) for kor, math, eng, name in input_data]

print()
students.sort(key=lambda x: -x[3])
for kor,math,eng,name in students:
    print(kor, math, eng,name)

 

결과

TypeError: bad operand type for unary -: 'str'

 

- 반환 값이 문자열이기 때문에 -를 붙일 수 없다.

- 숫자는 -를 붙여 절댓값이 크면 클수록 작기 때문에 내림차순으로 할 수 있었다.

- 이를 해결하기 위해 사전순으로 정렬 후, reverse=True를 추가한다.

 

input_data=[tuple(input().split()) for _ in range(5)]
students=[(int(kor),int(math),int(eng),name) for kor, math, eng, name in input_data]

print()
students.sort(key=lambda x: x[3],reverse=True)
for kor,math,eng,name in students:
    print(kor, math, eng,name)

 

결과

>> 30 50 60 john 
>> 70 60 90 tom 
>> 30 40 70 max
>> 20 60 40 jane
>> 90 60 50 beo

70 60 90 tom
30 40 70 max
30 50 60 john
20 60 40 jane
90 60 50 beo

 

- 클래스를 사용하여 문자열을 기준으로 정렬한 것은 다음과 같다.

class Student:
    def __init__(self,kor,math,eng,name):
        self.kor=kor
        self.math=math
        self.eng=eng
        self.name=name

input_data=[tuple(input().split()) for _ in range(5)]
students=[Student(int(kor),int(math),int(eng),name) for kor, math, eng, name in input_data]

print()
students.sort(key=lambda x: x.name)
for student in students:
    print(student.kor, student.math, student.eng,student.name)

print()
students.sort(key=lambda x: x.name,reverse=True)
for student in students:
    print(student.kor, student.math, student.eng,student.name)

 

결과

30 50 60 john 
70 60 90 tom 
30 40 70 max
20 60 40 jane
90 60 50 beo

# 이름 사전순
90 60 50 beo
20 60 40 jane
30 50 60 john
30 40 70 max
70 60 90 tom

# 이름 사전역순
70 60 90 tom
30 40 70 max
30 50 60 john
20 60 40 jane
90 60 50 beo