Big Bro's Studying Archive
Python 기초 6 : for 반복문, map함수, 리스트 내포표현식을 이용한 리스트 연산 본문
"""
Created on Fri Apr 10 10:17:32 2020
@author: Yoon Baek
"""
로또 생성 프로그램 만들어보기
import random
lot = []
while len(lot) <= 7 :
num = random.randrange(1,46)
if num in lot :
next
else :
lot.append(num)
lot.sort(reverse = False)
print(lot)
random 모듈의 randrange 함수를 활용해
1번부터 45번까지의 숫자를 랜덤으로 출력하고 정렬하는 프로그램
리스트 내포 표현식
- 리스트가 벡터연산이 안되는 점을 비교적 간단한 문법으로 가능하게 함
- 리스트 내부에 반복문/조건문의 축약형 형태 전달 가능
1. 문법
[ 리턴값 for 반복변수 in 대상 ] # 반복만 가능
[ 리턴값 for 반복변수 in 대상 if 조건 ] # else 생략 가능
[ 참리턴값 if 조건 else 거짓리턴값 for 반복변수 in 대상 ] # else 선언
예제) 아래 리스트에 10% 인상된 값 리턴
L1 = [1,2,3,4,5]
1) for 문
L2 = []
for i in L1 :
L2.append (i * 1.1)
L2
2) mapping
list(map(lambda x : x *1.1, L1))
3) list 내포 표현식
[i * 1.1 for i in L1]
예제2) 아래 리스트에서 3보다 작은 값만 출력
L1 = [1,2,3,4,5]
1) for문
L2 = []
for i in L1:
if i < 3 :
L2.append(i)
L2
2) map
list(map(lambda x : x if x < 3 else None, L1))
lambda에서 if를 쓸 때 else 생략이 안되고 간단한 if문만 가능하다.
3) list comprehension
[i for i in L1 if i < 3] # 가능
[i for i in L1 if i < 3 else i * 2] # 불가
[i if i < 3 else i * 2 for i in L1] # 가능
예제3) L1 리스트에서 3보다 작으면 'a' 크거나 같으면 'b' 리턴
['a' for i in L1 if i < 3 else 'b'] # 불가
['a' if i < 3 else 'b' for i in L1]
else값을 넣고 싶으면 if문을 통째로 앞으로 빼서 축약형으로 전달해야한다.
[ 연습 문제 ]
sal = ['9,900','25,000','13,000']
addr = ['a;b;c','aa;bb;cc','aaa;bbb;ccc']
comm = [1000,1600,2000]
위 리스트를 입력후 풀이해보자.
1) sal의 10% 인상값 출력
sol 1 : for 문
L2 = []
for i in sal:
i = i.replace(',','')
L2.append(round(int(i)*1.1))
L2
sol 2 : 매핑
f1 = lambda x : round(int(x.replace(',','')) * 1.1)
list(map(f1, sal))
sol 3 : 리스트 내포 표현식
[round(int(i.replace(',','')) * 1.1) for i in sal]
리스트 내포 표현식이 쿼리가 간단해서 애용하게 되는 듯 하다.
단 논리적 구조가 복잡할 때는 for문을 쓰게 되는 듯
2) addr에서 각 두번째 값(b,bb,bbb) 출력
sol 1 : for 반복문 이용
'b;b;b'.split(';')[1]
addr2 = []
for i in addr :
addr2.append(i.split(';')[1])
addr2
sol 2 : 매핑함수 이용
f2 = lambda x : x.split(';')[1]
list(map(f2, addr))
[ 참고 - map에 인자 전달 방식 ]
fchamgo = lambda x, y : x.split(';')[y]
list(map(fchamgo,addr, 1)) # map에 스칼라 숫자 전달
list(map(fchamgo,addr, [1]))
map은 서로 다른 리스트의 개수를 맞춰주는 기능이 없다.
따라서 아래와 같은 방식으로 사용자가 개수를 맞춰 전달해주어야 한다.
list(map(fchamgo,addr, [1,1,1]))
근데 언제까지 이런식으로 할 것인가?
pandas의 map 유사 기능이나 다른 적용함수는 가능한 것들이 있으므로 활용
sol 3 : 리스트 내포 표현식 활용
[ i.split(';')[1] for i in addr ]
3) comm이 1500보다 큰 경우 'A', 아니면 'B' 출력
sol 1
comm2 = []
for i in comm:
if i > 1500 :
comm2.append('A')
else :
comm2.append('B')
comm2
sol 2
f3 = lambda x : 'A' if x > 1500 else 'B'
list(map(f3, comm))
sol 3
['A' if i > 1500 else 'B' for i in comm]
sol 4 : np.where의 활용
np.where(np.array(comm) > 1500, 'A', 'B')
numpy의 np.where 함수를 활용할 수 있다.
R의 ifelse함수와 똑같은 역할을 하는 함수.
다만 array에만 적용가능한 함수이므로
리스트인 경우 형을 array로 변환해주자.
deep copy
L1 = [1,2,3]
L2 = L1
L1 [0] = 10
L1
L2
L2도 1번째 원소가 같이 변한 것을 확인
파이썬의 특징 : 메모리 공유
L2[2] = 9
L1
L2를 바꿔도 L1이 변함
L1 = [1,2,3]
L1 = L3[:]
메모리 분리 (완벽히 다른 개체)
백업을 원할 경우는 이렇게 해야.
[ 참고 : 객체의 메모리 주소 확인 ]
id(L1) # 1287198669768
id(L2) # 1287198669768 L1과 L2는 같음을 확인
id(L3) # 1287198016136
[실습문제]
아래문제들은 난이도가 있음에 유의.
풀기 어렵더라도 집착하지 않아도 된다.
1. oracle translate와 같은 함수 생성
예시) f_translate('abcdea','abc','ABC') => 'ABCdeA'
def f_translate(word, target, change):
if len(target) <= len(change):
res = word
for i in range(0,len(target)):
for j in range(0,len(word)):
if target[i] == word[j]:
res = res.replace(word[j],change[i])
else :
pass
elif len(change) != 0 :
res = word
for i in range(1, len(target)-len(change)+1):
res = res.replace(target[-i],'')
for i in range(0,len(change)):
for j in range(0,len(res)):
if target[i] == res[j]:
res = res.replace(res[j],change[i])
else :
pass
else :
res = word
for i in range(1, len(target)-len(change)+1):
res = res.replace(target[-i],'')
return(res)
f_translate('abcd ea','a bc','ABC')
2. oracle instr과 같은 함수 생성(없으면 -1 생성)
예시) f_instr(data,pattern,start=0,n=1)
풀이 1
def f_instr(data, pattern, start = 0, n = 1):
match = []
for i in range(0, len(data)-len(pattern)+1):
if data[i:i+len(pattern)] == pattern :
match.append(i)
else :
next
if len(match) != 0:
for j in range(0, len(match)):
if match[j] < start :
match.remove(j)
else:
next
print(match[n - 1])
else:
print(-1)
match
len(match)
'aaaaa'.find('a',3)
match[1]
f_instr('abcda','c', start = 1 ,n = 2)
match.remove(0)
풀이 2
def f_instr(data, pattern ,start, n):
for i in range(0,n) :
position = data.find(pattern, start)
start = position + 1
return position
f_instr('abcdae', 'a', 1, 2)
3. 1~100까지의 누적합 계산시 최초로 누적합이 1000을 넘는 숫자 출력
i = 0
vsum = 0
for i in range(1,101) :
if vsum >= 1000 :
break
else :
vsum += i
i += 1
print ('%d에서 누적합이 1000을 넘습니다.' % i)
'Big Data展' 카테고리의 다른 글
R로 접하는 통계 : T - test (0) | 2020.05.03 |
---|---|
SQL by Oracle #6 outer join과 다양한 서브쿼리 (0) | 2020.04.24 |
R 프로그래밍 입문 (2) 벡터의 생성, 색인, 수정, Boolean 색인, 형확인함수, 논리 연산자 (0) | 2020.04.17 |
R 프로그래밍 입문 (1) 변수의 선언과 기본적인 형변환함수, 날짜함수 (0) | 2020.04.16 |
SQL by Oracle # 5. group by와 join, union & 실습문제 (0) | 2020.04.14 |