2019.03.14 TIL
(TIL은 스스로 이해한 것을 바탕으로 정리한 것으로 오류가 있을 수 있습니다)
# 질문에 답하기
- filter, map, reduce에 대해 이야기 해보기
filter
기본 문법
filter(f, iterable)
- filter는 여러개의 값들이 있을 때 특정한 기준에 대해 블리언을 적용하여 뽑아내는 것이다.
ex)
li = [-3, 5, 1, 2, -5, -4, 14] # 이 리스트 중에서 음수를 제거하고 싶다라고 하면
f = filter(lambda a: a>0, li) # filter을 활용하여 간단하게 끝낼 수 있다. but 하나씩 꺼낼 수 있다
- 여기서 lazy evaluation이 나와야 한다.
lazy evaluation
lazy evaluation은 내가 원할 때 마다 결과값을 가지고 오는 것이다.
즉 함수의 실행시기를 내가 결정하게 된다.
이것이 filter, map, reduce, generator의 큰 특징이다.
filter, map, reduce는 모두 generator의 일종이다.
다시 돌아와서 위에
f = filter(lambda a: a>0, li) # next(f)라는 것으로 f에 해당하는 요소를 하나씩 뽑아낸다.
# 이것을 다 뽑아 보기 위해서는
for e in f:
print(e)
# 이것을 리스트로 만들기 위해서는
li = []
for e in f:
li.append(e)
# 혹은 한번에 적어줄 수도 있다.
result = []
for elem in li:
if elem>0:
result.append(elem)
# 같이 한번에 적어줄 수도 있게 되었다.
# 또 한줄로 적어줄 수도 있다.
# 홀수 리스트로 한번에 뽑아내기
li2 = list(filter(lambda x: x%2, li)) # 한번에 리스트로 뽑아낸다.
# 짝수 리스트 한번에 뽑아내기
li2 = list(filter(lambda x:x%2==0, li))
- filter는 특정한 f(x)에 대해 bloolean값을 필터하여 뽑아낸다.
- 내가 다른 작업을 하다가 next(f)를 통해 하나를 뽑아내고 또 이후에 next(f)를 함으로서 그 다음 값들을 뽑아 올 수 있다. 메모리를 따로 쓰지 않는다는 장점이 있다.
- 내가 함수의 실행시간을 결정할 수 있다는 것과, 메모리를 따로 저장하지 않고 바로 가지고 올 수 있다.
- 내가 원하는 시점에 그때 작용(lazy evaluation)
- 컴퓨터 프로그래밍에서 느긋한 계산법(Lazy evaluation)은 계산의 결과값이 필요할 때까지 계산을 늦추는 기법이다. 두 가지 관련된 항목들이 있는데 지연 계산법과 최소 계산법이다.
- 느긋하게 계산하면 필요없는 계산을 하지 않으므로 실행을 더 빠르게 할 수 있고, 복합 수식을 계산할 때 오류 상태를 피할 수 있고, 무한 자료 구조를 쓸 수 있고, 미리 정의된 것을 이용하지 않고 보통 함수로 제어 구조를 정의할 수 있다.
- 느긋한 계산법을 사용하는 언어들은 “이름으로 호출”하거나 “필요할 때 호출”하는 계산 전략을 사용하는 것으로 나눌 수 있다. 하스켈과 같은 대부분의 실제 느긋한 언어들은 성능상의 이유로 “필요할 때 호출” 전략을 사용한다. 그러나 느긋한 계산법을 이론적으로 표현한 것들은 간편하게 “이름으로 호출”하기도 한다.
map
map 기본 문법
map(f, iterable) #mapobject를 반환한다. map은 함수와 iterable을 받는다.
- 특정한 f(x)를 적용하여 새롭게 값을 뽑아내는 것. 이것을 선형대수에서는 사상이라고 한다.
ex)
li = [2, 3, 4, 5] # 여기에 있는 값을 제곱을 하여 하나씩 뽑아내보자.
m = map(lambda x: x**2, li)
next(m)
- 맵에서 나온것 맵객체 필터에서 나온건 필터객체 이건 generator 객체에 포함되고 이건 또 iterator에 포함된다. 따라서 generator로 순회할 수 있다. iterator는 포문을 쓸 수 있으므로 map과 filter 역시 포문을 쓸 수 있다.
filter와 map을 함꼐 사용하여 풀어야 하는 문제
li = [ 2, 3, -5, 6, -2, 1, -10] # 양수를 골라내어 제곱한 값을 리스트로 만드시오
a = list(map(lambda x: x**2 , filter(lambda y: y>0, li)))
reduce
자료구조 (list,tuple)를 연산을 통해서 단 하나의 값으로 만드는 함수이다.
reduce는 내장함수가 아니므로 import를 해서 불러줘야한다.
from functools import reduce
help(reduce) #함수는 기본적으로 이름, 인자 , 반환값을 꼭 적어줘야한다.
reduce(function, sequence[, initial]) -> value
"""
여기서 function 에는 람다가
sequence에는 자료구조(iterable)이 들어갈 것이고 initial은 초기값이 들어갈 것이다.
그리고 return 값으로는 하나의 value가 나와야 한다.
"""
# reduce는 기본적으로 2개의 인자를 받는다.
li = [2, 3, -5, 6, -2, 1, -10]
result = reduce(lambda x,y : x+y, li)
result = reduce(lambda x,y: x+y, li, 100) # 100이 초기 x에 들어가도록 초기값 설정이 가능하다.
list의 최대 요소 구하기
li = [3,6,8,-10,2,1, 100, 50, 46, -47]
from functools import reduce
result = reduce(rambda x,y : x if x>y else y, li) (삼차다항식이용)
문자수 세기
li =[“a”, “b”, “a”, “b”, “b”, “a”, “c”, “a”]가 주어졌을 때 dic ={‘a’:4, ‘b’:3, ‘c’:1} —->크롤링해서 좋아요 혹은 싫어요 핸들링 할 때 사용
위와 같이 dictionary를 뽑아내자.
첫번쨰 참고 : 파이썬의 함수는 식이므로 무조건 값을 반환(None도 반환)
두번째 참고 : 논리 연산을 할 때 마지막으로 참조한 값을 반환한다.[1,2] or [] —> [1,2]라는 값을 반환한다.
dic.get(“a”,0) + 1 —> value로 활용하고
dic.update({“a”:3, “b” : 4})
초기값 딕셔너리
import reduce
li =["a", "b", "a", "b", "b", "a", "c", "a"]
result = reduce(lambda dic,cha : dic.update({cha : dic.get(cha,0)+1}) or dic, li, {})