본문 바로가기

programming study/Python

[우리밋_woorimIT] Python 배열,리스트,2차원 배열 (2020.12.24)

본 내용은 해당 강의1, 강의2 토대로 작성


Iterable

Python에서 데이터가 반복해서 나타나는 형태의 객체들은 Iterable 이라고 정의한다. 아래와 같은 것들이 있다.

  • List
  • Tuple
  • Set
  • Dictionary

Iterable 안에 있는 데이터를 다루는 괄호에 따라 아래와 같이 분류 된다.

1차원 [1,2,3]

2차원 [ [1,2,3] , [4,5,6] ]

배열과 리스트

배열과 리스트는 같은 자료형의 데이터들을 하나의 변수로 정의한다는 것에서 공통점을 갖는다. 하지만, 배열은 같은 자료형의 데이터들을 하나의 변수로 정의할 수 있고 리스트는 서로 다른 자료형이 데이터들도 하나의 변수로 정의할 수 있다.

array = int, int, int, int …

list = int, float, string, list …

배열과 리스트는 모두 메모리 저장공간을 사용한다. 데이터가 입력됨에 따라서 각 주소마다 해당하는 데이터를 저장한다. 여기서, 배열은 메모리 주소를 순차적으로, 리스트는 임의대로 저장하되, 각 데이터가 다음 주소를 가르키는 포인터가 있다. 아래의 그림을 참고하자

스크린샷 2020-12-24 오후 7.04.09

데이터 검색

각각의 경우에서 특정한 데이터를 찾을 때, 아래와 같은 차이를 보인다.

array[0] -> 처음에 있는 것

list[0] -> 처음에 있는 것

array[3] -> 3번에 해당하는 데이터

list[3] -> 리스트의 맨 처음 주소 -> 다음 번지 -> 다음 번지 -> … 3번이 나올 때 까지

즉, 리스트는 주소가 임의로 되어있어서 특정 데이터를 찾을 때, 맨 처음 주소로 이동하여 그 주소에 저장되어 있는 다음 번지의 주소를 찾아가고 이후에도 이 동작을 특정 데이터의 주소까지 반복한다. 배열은 원하는 데이터를 바로 찾을 수 있지만, 리스트는 처음부터 찾아봐야하기 때문에 검색이 느려진다.

데이터 삭제

데이터를 삭제할 때, 배열은 해당 데이터가 위치하던 메모리 공간이 그대로 남는다. 그리고 그 공간을 채우기 위해서 뒤의 값들을 앞으로 당겨온다. 이런 과정에서 시간이 더 소요되고 메모리 공간이 낭비된다. 반면, 리스트는 포인터만 바꾸면 되기 때문에 메모리를 더 효율적으로 사용한다.

스크린샷 2020-12-24 오후 7.04.15

데이터 삽입

새로운 데이터를 넣을 때, 배열은 기존 값들을 뒤로 밀어내고 새 값을 넣는다. 리스트는 새 값을 바로 넣고 포인터를 만들어준다.

스크린샷 2020-12-24 오후 7.04.26

배열의 끝을 리스트 앞에 연결할 시 포인터가 연결 된다.

스크린샷 2020-12-24 오후 7.04.31

배열을 중간에 삽입하면 아래처럼 포인터가 끝에 연결된다.

스크린샷 2020-12-24 오후 7.04.38

즉, 리스트는 포인터를 사용하기 때문에 데이터의 삭제, 삽입에서 메모리를 효율적으로 사용한다.

정리

Array List
순차적 주소 임의 주소, 포인터
같은 자료형 여러가지의 자료형
빠른 검색 느린 검색
메모리 비효율 메모리 효율

2차원 배열

1차원 배열이 많이 생겼을 때, 2차원 배열을 이용해서 한 번에 저장할 수 있다.

2행 3열의 2차원 배열과 호출 형식은 아래와 같다.

0,0 0,1 0,2
1,0 1,1 1,2

Python 2차원 배열 선언

array = [[0 for _ in range(5)]for _ in range(3)]

이것은 고유 문법이다. Python의 배열은 리스트 형식이라서 공간과 데이터를 같이 선언해야만 한다. 위의 명령어는 0이 다섯 개 있는 행을 3번 반복해서 만든다는 의미이다.

위의 방법 말고 더 간단하게 2차원 배열을 선언할 수 있는 numpy라이브러리가 있다.

import numpy
array = numpy.arange(15).reshape(3,5);

arange함수는 범위 지정 함수이다. 0~14의 범위를 지정하고 뒤의 reshape 로 3행 5열 2차원 배열을 만들 수 있다.

array = numpy.zeros((3,5));
arraay = numpy.ones((3,5));

위의 두 함수는 3행 5열의 배열을 생성 후 zeros는 0을 채우고 ones는 1을 채운다.

2차원 배열 연습문제 - 내 미래

문제

훈련병인 철수는 교관의 지시에 따라야한다.

교관은 "좌로 1보, 하로 2보 가!"와 같이 좌,우,상,하로 이동할 것을 명령한다.

철수의 현재 위치가 입력으로 주어질 때 교관의 명령대로 이동한 위치는 어디일까?

제한 조건

철수의 현재 위치는 첫 입력 값으로 공백을 두고 입력

훈련소의 전체 공간 크기는 5*5

교관이 지시한 명령은 절대 훈련소 공간을 벗어나지 않음

좌는 왼쪽, 우는 오른쪽, 상은 위쪽, 하는 아래쪽

입력은 좌,우,상,하의 순서대로 공백을 두고 입력

입력

3 3
1 2 1 3

출력

0 0 0 0 0 
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 0 

풀이

import numpy as np # numpy 호출
cur = tuple(int, input().split());  # 철수의 현재 위치, 변하지 않는 tuple 사용
lft, rgt, up, down = map(int, input().split()); # 좌우상하 입력
coords = np.zeros( (5,5), dtype = int ) # 5*5 2차원 배열 생성, int타입
move = ( cur[0] -up +down , cur[1] -lft + rgt )
coords[move[0] -1][move[1] -1] = 1 # 배열의 범위를 넘지 않도록 -1

for crd in coords:
  print( *crd) # Asterisk로 Unpacking

느낀점

오늘 Codeup 기초 100제를 푸는데 바둑판 십자 뒤집기에서 막혀버렸다. 웹 서치를 해봐도 관련 개념이 없으니 너무나 답답해서 유튜브에서 좋은 강의를 찾아서 들었다. 리스트와 배열의 차이를 인지하지 못 했었는데 명료하게 잘 이해가 되었고 Python에서 2차 배열을 다루는 것에 대해서도 숙지가 되었다. 자… 이제 다시 문제 풀러….