파이썬 리스트 정수 추출 - paisseon liseuteu jeongsu chuchul

파이썬 중복 없이 난수 추출 / 리스트에서 값 뽑기 방법 정리

파이썬에서 중복을 허가하지 않고 특정 범위 내의 숫자(정수)들 중 원하는 개수의 숫자들을 뽑거나

리스트 내에서 특정 개수의 자료들을 샘플링하는 방법을 정리해보겠습니다.

중복되지 않게 숫자들을 뽑기

이 과정은 넘파이의 random.choice 함수를 사용하시면 편리한데,

np.random.choice(range(시작 숫자, 끝 숫자+1), 개수, replace = False) 형태의 코드로

원하는 시작 숫자 ~ 끝 숫자 범위 내에서 특정 개수만큼 중복 없이 난수 샘플링이 가능합니다.

가령, 로또 번호의 예시로 1~45의 숫자들 중 6개를 뽑는 방법은 다음과 같습니다.

import numpy as np

# 1~45 중 중복 없이 6개 숫자 추출
numbers = np.random.choice(range(1, 46), 6, replace=False)

print(numbers) # [26 35 44 21 19 22]

위에서 함수 실행 결과(numbers)는 numpy array 자료형이므로,

리스트 변환을 원하시면 numbers = list(numbers) 형태의 코드로 변환을 해주시면 됩니다.

중복되지 않게 리스트 내에서 값들을 랜덤 추출하기

이 경우도 위처럼 넘파이의 random.choice 함수를 적용하여 편리하게 추출이 가능합니다.

np.random.choice(리스트, 개수, replace = False) 형태의 코드로

리스트 내에서 특정 개수의 자료를 중복 없이 가져올 수 있습니다.

또한, p 인자를 통하여 추출될 확률들의 리스트도 지정 가능하니 참고하세요.

(미지정 시 균일 확률이며, p 리스트 숫자 합계는 1이어야 하고, 난수 추출에도 적용 가능합니다.)

# 리스트에서 자료 2개 중복 없이 샘플링(균등 확률)
sample1 = np.random.choice(['A', 'B', 'C', 'D', 'E'], 2, replace=False)

print(sample1) # ['C' 'B']

# 리스트에서 자료 2개 중복 없이 샘플링(확률 지정)
sample2 = np.random.choice(['A', 'B', 'C', 'D', 'E'], 2, replace=False, p = [0.5, 0.47, 0.01, 0.01, 0.01])

print(sample2) # ['B' 'A']

마찬가지로, 반환된 결과의 자료형은 넘파이 배열 타입이라는 점을 참고해주세요.

이번에는 리스트에 map 함수를 사용해보겠습니다. map은 리스트의 요소를 지정된 함수로 처리해주는 함수입니다(튜플에도 map 함수를 사용할 수 있으며 원본 튜플을 변경하는 것이 아니라 새 튜플을 생성합니다).

  • list(map(함수, 리스트))
  • tuple(map(함수, 튜플))

예를 들어 실수가 저장된 리스트가 있을 때 이 리스트의 모든 요소를 정수로 변환하려면 어떻게 해야 할까요? 먼저 for 반복문을 사용해서 변환해보겠습니다.

>>> a = [1.2, 2.5, 3.7, 4.6]
>>> for i in range(len(a)):
...     a[i] = int(a[i])
...
>>> a
[1, 2, 3, 4]

forrange(len(a))를 사용해서 인덱스를 가져왔습니다. 그리고 가져온 인덱스로 요소 하나하나에 접근한 뒤 int로 변환하여 다시 저장했습니다.

매번 for 반복문으로 반복하면서 요소를 변환하려니 조금 번거롭습니다. 이때는 map 함수를 사용하면 편리합니다.

>>> a = [1.2, 2.5, 3.7, 4.6]
>>> a = list(map(int, a))
>>> a
[1, 2, 3, 4]

a = list(map(int, a)) 한 줄로 변환이 끝났습니다. mapint와 리스트를 넣으면 리스트의 모든 요소를 int를 사용해서 변환합니다. 그리고 list를 사용해서 map의 결과를 다시 리스트로 만들어줍니다.

그림 20-5 리스트에 map 함수 사용
파이썬 리스트 정수 추출 - paisseon liseuteu jeongsu chuchul

사실 map에는 리스트뿐만 아니라 모든 반복 가능한 객체를 넣을 수 있습니다. 여기서는 range를 사용해서 숫자를 만든 뒤에 숫자를 문자열로 변환해보겠습니다.

>>> a = list(map(str, range(10)))
>>> a
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

range로 0부터 9까지 숫자를 만들고, str을 이용해서 모두 문자열로 변환했습니다. 리스트를 출력해보면 각 요소가 ' '(작은따옴표)로 묶인 것을 볼 수 있습니다.

지금까지 input().split()으로 값을 여러 개 입력받고 정수, 실수로 변환할 때도 map을 사용했었죠? 사실 input().split()의 결과가 문자열 리스트라서 map을 사용할 수 있었습니다.

다음과 같이 input().split()을 사용한 뒤에 변수 한 개에 저장해보면 리스트인지 확인할 수 있습니다.

>>> a = input().split()
10 20 (입력)
>>> a
['10', '20']

10 20을 입력하면 ['10', '20']처럼 문자열 두 개가 들어있는 리스트가 만들어집니다.

이제 map을 사용해서 정수로 변환해봅시다.

>>> a = map(int, input().split())
10 20 (입력)
>>> a
<map object at 0x03DFB0D0>
>>> list(a)
[10, 20]

다시 10 20을 입력하면 맵 객체(map object)가 만들어집니다. 이 상태로는 안에 들어있는 값을 볼 수 없으므로 list를 사용해서 리스트로 출력했습니다. 리스트를 보면 [10, 20]처럼 정수 두 개가 들어있습니다.

이 리스트를 변수 두 개에 저장하면 지금까지 사용한 a, b = map(int, input().split())와 같은 동작이 됩니다.

>>> a, b = [10, 20]
>>> a
10
>>> b
20

사실 map 함수가 반환하는 맵 객체는 이터레이터라서 변수 여러 개에 저장하는 언패킹(unpacking)이 가능합니다. 그래서 a, b = map(int, input().split())처럼 list를 생략한 것입니다.

a, b = map(int, input().split())을 풀어서 쓰면 다음과 같은 코드가 됩니다.

x = input().split()    # input().split()의 결과는 문자열 리스트
x = map(int, x)        # 리스트의 요소를 int로 변환, 결과는 맵 객체
a, b = x               # 맵 객체는 변수 여러 개에 저장할 수 있음

내용이 조금 어렵죠? 이처럼 파이썬은 여러 가지 함수를 조합해서 결과를 만들어냅니다. 초보때는 이해하기가 쉽지 않은 부분이니 이런 것도 있구나 하고 넘어가도 됩니다.