Python: 2차원 List 문제 풀이

0

압축 Python

목록 보기
5/11
post-thumbnail
학번이메일국어영어수학과학국사총점담임코드성취도지역코드
숫자문자숫자숫자숫자숫자숫자숫자문자문자문자
64333333111

*csv 파일의 일부분

990001,addx, 17, 29, 16, 49, 43,154,C,A,C
990002,stch, 30,  9, 48, 25, 81,193,C,A,A
990003,gali, 93, 60,  6, 84, 36,279,A,C,A
990004,miat, 73, 22, 48, 24, 72,239,B,C,C
990005,oran, 33, 38, 59, 58, 28,216,C,B,A
990006,sj24, 27, 65, 54, 77, 33,256,B,A,A
990007,kor2, 33, 85, 98, 60, 66,342,A,B,A
990008,vsky, 41,  5, 99, 14, 67,226,C,A,C
990009,kimd, 74,  4,  1, 33, 53,165,B,C,A
990010,blue, 55, 84, 50, 89, 37,315,A,B,A
990011,moja, 43, 69, 68, 23, 92,295,B,A,C
990012,bleu, 15,  5, 19, 97, 88,224,B,C,C
990013,lore, 77, 85, 36, 95, 46,339,B,A,C
990014,oldn, 83, 89, 67, 67, 87,393,B,C,A
990015,sire, 66, 45, 86, 93, 48,338,C,B,A
990016,klaa, 73,  4, 40, 31, 95,243,A,B,C
990017,rsh1, 47,  1, 63, 63, 22,196,B,A,A
990018,vict, 79, 17, 32, 29, 85,242,C,A,C
990019,popy, 95, 65, 65, 29, 75,329,B,A,C
990020,kbsu, 37, 52, 24, 37, 93,243,C,A,C
990021,equi, 13, 95, 56, 93, 88,345,B,C,B
990022,schn, 19, 92, 49, 84, 54,298,A,B,A
990023,tess, 86, 71, 87,  6, 15,265,B,C,B
990024,mula, 48, 41, 18, 32, 46,185,A,B,C
990025,lyj2, 24, 90, 72, 29, 52,267,B,A,B
990026,netm, 65,  4,  4, 23, 45,141,B,C,B
990027,21nj, 41, 41, 93, 73, 22,270,B,A,C
990028,brea, 63, 42, 19, 32, 53,209,C,B,C
990029,minh,  3, 11, 89, 71, 88,262,B,C,B
990030,seac, 73, 57, 37, 44, 18,229,A,C,A
990031,simo,  5, 73, 26, 34, 35,173,A,C,B
990032,sonn, 90, 18, 84, 18, 80,290,C,B,B
990033,mrsw, 90, 71,  9, 16, 57,243,B,C,A
990034,soyo,100, 39, 44, 89, 88,360,A,C,A
990035,lswp, 31, 37, 25, 86, 35,214,A,C,B
990036,bums,  1, 59, 36, 25, 48,169,A,C,B
990037,gibb, 76, 61,  4, 14, 54,209,A,C,A
990038,maxp, 43, 48, 76,  3, 68,238,A,C,B
990039,huff, 52, 99, 97, 87, 72,407,A,C,A
990040,sand, 48, 43, 79, 46, 88,304,A,C,B
990041,blui, 25, 30,  2, 14, 62,133,B,C,B
990042,sd95, 88, 27, 72, 85, 63,335,B,C,A
990043,ksg6, 90, 13, 19, 22, 91,235,A,B,C
990044,lks5, 91, 12,  4, 73, 13,193,A,B,A
990045,ddae, 69, 81, 28, 63, 93,334,C,A,A
990046,paco, 75, 53,  4, 91,  4,227,B,A,B
990047,sgtj, 27, 77,  6, 63, 82,255,C,A,C
990048,best,  3, 19, 10, 30, 39,101,A,B,C
990049,head, 45, 71, 94, 75, 72,357,C,B,A
990050,youo, 25, 66, 51, 99, 42,283,C,A,C


풀이를 위한 데이터 전처리

목표: 주어진 데이터를 중첩 리스트로 만들어서 데이터 핸들링

  • csv파일을 editor에서 python을 활용하여 불러온다
# python: open()함수를 사용한 외부 파일 읽어들이기

# 해당 파일의 경로를 변수에 할당(하지 않고 직접 입력해도 무관)
path = './file_name.csv'

# open()을 사용
# 첫 번째 파라미터: 경로 
# 두 번째 파라미터: 읽기모드(r: 읽기전용, w: 쓰기모드, a: 추가)
file = open(path, 'r')

# 읽기로 불러와서 변수에 할당하여 원본을 유지하면서 작업
# readlines() 메서드를 사용
# file의 모든 내용을 lines에 할당한다
lines = file.readlines()
  • readlines()는 파일의 모든 줄을 읽어서 한 줄이 끝날 때마다 \n을 첨가하여 리스트로 반환한다

    ['990001,addx, 17, 29, 16, 49, 43,154,C,A,C\n',
    '990002,stch, 30,  9, 48, 25, 81,193,C,A,A\n', 
    '990003,gali, 93, 60,  6, 84, 36,279,A,C,A\n',
    ...
    ]

    한 줄을 단위로 ''가 양쪽에 붙어 있고 마지막에는 \n가 붙어있다.
    990001, addx 등을 요소로 가지는 중첩 리스트처럼 보이지만 ''로 묶여 있는 문자열들을 요소로 가지는 (1차원) 리스트이다.

  • split() 메서드를 사용하여 ''로 묶인 문자열을 ,단위로 분리하여 한 줄씩 리스트로 만든다

  • 이렇게 만들어진 리스트를 새로운 리스트에 append()를 활용하여 넣어주면 중첩 리스트가 만들어진다

  • 단, 이 과정에서 숫자로 이루어진 문자열은 숫자로 변환해준다

# 사용할 중첩 리스트를 미리 선언
list_lines = []

for i in lines:
	# split()을 활용하여 , 단위로 분리한다
    temp = i[0:-1].split(',')
    
    # 분리한 리스트에서 숫자로 바꿔야 할 부분을 숫자로 바꾼다(type() 활용)
    for i in range(2,len(temp)-3):
        if type(temp[i]) != int:
            temp[i] = int(temp[i])
        if type(temp[0]) != int:
            temp[0] = int(temp[0])    
    list_lines.append(temp)
    
    # 분리한 리스트에서 숫자로 바꿔야 할 부분을 숫자로 바꾼다(isnumeric() 활용)
    for i in range(len(temp)-3):
    # isnumeric()은 해당 자료형이 숫자인지 판별하는 것이 아니다
    # 해당 '문자열'이 '숫자 리터럴'로 구성되어 있는지를 판별한다
        if temp[i].strip().isnumeric():
            temp[i] = int(temp[i])    
    list_lines.append(temp)
    
print(list_lines)

>>
[[990001, 'addx', 17, 29, 16, 49, 43, 154, 'C', 'A', 'C'],
[990002, 'stch', 30, 9, 48, 25, 81, 193, 'C', 'A', 'A'],
[990003, 'gali', 93, 60, 6, 84, 36, 279, 'A', 'C', 'A'],
...
]

이렇게 리스트를 요소로 갖는 리스트 즉, 중첩 리스트가 생성되었다.

중첩 리스트 내부에 있는 각 리스트들은 한 명의 정보를 의미한다는 것을 쉽게 알 수 있게 되었다.


문제 1

지역코드가 B인 자료에 대하여 '국어+영어'의 결과로 내림차순 정렬했을 때 다섯 번째 학번 출력할 것. (단, 동점자가 있다면 학번에 대한 오름차순으로 정렬.)

  • 풀이
    1. 지역코드가 B인 자료를 선별하여 새로운 리스트에 넣어준다
    2. 국어 점수와 영어 점수를 합산하고 이 데이터를 학번과 함께 또 다른 새 리스트에 넣어준다
    3. 마지막으로 생성한 리스트에서 동점이 있는지 검사하고 동점자는 학번으로 정렬한다
    4. 4번 인덱스 값을 찾는다
# 지역코드 B 찾기

# 지역코드 B인 인원만 모아둘 리스트 생성
list_code_b = []

for i in list_lines:
	# 학번코드 인덱스를 조회하여 'B'라면 append() 실행
    if i[-1] == 'B':
        list_code_b.append(i)
        
print(list_code_b)

>>
[[990021, 'equi', 13, 95, 56, 93, 88, 345, 'B', 'C', 'B'],
[990023, 'tess', 86, 71, 87, 6, 15, 265, 'B', 'C', 'B'], 
[990025, 'lyj2', 24, 90, 72, 29, 52, 267, 'B', 'A', 'B'],
...
]

# 국어점수 + 영어점수로 내림차순 정렬하기
# 동일한 점수일 때 학번으로 정렬하기
# 국어점수: 2 / 영어점수: 3

# 합계 구하기
# 학번 가져오기

# 앞서 생성한 지역코드 'B' 리스트의 요소 중에서
# 점수의 합계와 학번 정보만을 담아둘 새로운 리스트 생성
list_score_sum = []

for i in list_code_b:
    total = 0
    total = i[2] + i[3]
    data = [i[0], total]
    list_score_sum.append(data)

# 점수로 서열 정리
for j in range(0, len(list_score_sum)-1):
    # j는 고정 값 (list)
    # j==0 -> list_score_sum[0]
    for k in range(j+1, len(list_score_sum)):
        # k는 비교 값
        if list_score_sum[j][1] < list_score_sum[k][1]:
            temp = list_score_sum[j][1]
            list_score_sum[j][1] = list_score_sum[k][1]
            list_score_sum[k][1] = temp
            
            
# 점수가 같다면 학번으로 서열 정리
for j in range(0, len(list_score_sum)-1):
    # j는 고정 값 (list)
    # j==0 -> list_score_sum[0]
    for k in range(j+1, len(list_score_sum)):
        # k는 비교 값
        if list_score_sum[j][1] == list_score_sum[k][1]:
            if list_score_sum[j][0] > list_score_sum[k][0]:
                temp = list_score_sum[j]
                list_score_sum[j] = list_score_sum[k]
                list_score_sum[k] = temp
            
# print(list_score_sum)
print(f"다섯 번째 학번은: {list_score_sum[4][0]}")

문제 2

지역코드가 B인 자료에 대하여 '국어+영어'의 점수 중에서 가장 큰 값을 출력하되, 동일한 값이 있을 때는 한 번만 출력하시오.

가장 큰 값이 동일하게 몇 개가 있어도 가장 큰 수
중복 제거로 이해하고 풀이

  • 풀이
    • 이미 국어+영어 합계를 구해놓은 리스트가 있다
    • 이 리스트에서 중복을 제거하고 인덱스가 0인 값을 출력한다
# 지역코드가 b인 자료를 모아 놓은 리스트 이름: list_code_b
# 지역코드가 b이면서 국어+영어 합계를 모아 놓은 리스트 이름: list_score_sum

# 필요 없는 데이터를 제외하고 오직 합계 점수만 담을 리스트 생성
score = []

# 합계 점수만 append() 실행
for i in list_score_sum:
    score.append(i[1])

여기서 중복만 제거해주면 된다.

  • 메모화와 같은 원리를 이용한다
  • 점수 리스트를 하나씩 꺼내면서 새로운 점수 리스트에 존재하지 않는 값은 append()를 실행
  • 새로운 점수 리스트에 이미 존재한다면 아무 일도 일어나지 않는다
  • 최댓값이 0번 인덱스로 정렬된 상태의 리스트에서 순서대로 꺼내기 때문에 따로 정렬할 필요가 없어지는 것도 장점이다
# 새로운 점수 리스트 생성
result = []

# 기본 점수 리스트에서 자료를 하나씩 꺼낸다
for value in score:
	# 새로운 점수 리스트에 존재하지 않는 값이라면
    if value not in result:
    	# append()를 실행
        result.append(value)

#
print(result[0])

문제 3

표를 참조하여 '영어+수학'이 120점 이상인 자료의 '총점+포인트'의 합계를 구하라

  • 담임코드에 따른 포인트

    ABC
    51520

  • 풀이
    • 처음에 구해둔 전처리 결과 리스트를 사용한다
    • 영어와 수학 점수를 조회하고 둘을 더한 값이 120 이상인지 판단한다
    • 120 이상이라면 새로운 점수 리스트에 append()실행
 # 영어:3 / 수학:4 / 총점:7 / 담임코드: 8
  # 새로운 리스트 생성
 new_lines = []

  # 자료를 순회한다
 for i in range(len(list_lines)):
    # i번째 인원의 영어 및 수학점수를 더하여 120 이상인지를 판단
    if list_lines[i][3] + list_lines[i][4] > 120:
    # 참이라면 append() 실행
      new_lines.append(list_lines[i])

이렇게 120점 이상만 모은 new_lines를 다시 순회하며 담임코드를 체크한다.

 # 코드에 따른 점수 변수화
A = 5
B = 15
C = 20

# 총점에 모든 점수를 바로 더할 수 있도록 변수화
total = 0

# 자료를 순회하면서 담임코드를 조회한다
for i in new_lines:
    # 총점을 미리 합계에 넣어둔다
    total += i[7]
    # 담임코드에 따른 점수를 추가로 부여한다
    if i[8]=="A":
        total += 5
    if i[8]=="B":
        total += 15
    if i[8]=="C":
        total += 20

print(total)

문제 4

표를 참조하여 성취도가 A 또는 B인 자료에 대해 '국어 + 지역포인트'가 50점 이상인 자료의 건수는 몇 건인가?

  • 지역코드에 따른 포인트

    ABC
    51015
  • 풀이

    • 건수를 저장할 변수를 생성한다
    • 조건에 맞는 자료를 넣을 새로운 리스트를 생성한다
    • 성취도가 C가 아니라면 새로운 리스트에 저장한다
# 건수를 저장할 변수 선언
count = 0

# 조건에 맞는 자료를 저장할 리스트 선언
last_lines = []

# 성취도: 9 
for i in list_lines:
    if i[9] != 'C':
        last_lines.append(i)
  • 각 인원마다 지역 포인트를 조회한다
  • 포인트와 국어점수를 더하여 50점 이상이라면 변수에 1을 더한다
  • 건수를 저장하는 변수를 출력한다
# 지역코드에 따른 포인트를 저장할 변수 선언
point = 0

# 지역코드에 따른 포인트 조회 및 저장
for i in last_lines:
    if i[8] == 'A':
        point = 5
    elif i[8] == 'B':
        point = 10
    elif i[8] == 'C':
        point = 15
    # 조건 확인
    if point + i[3] >=50:
        count += 1

0개의 댓글