아무래도, 파이썬에서는 filter, map, reduce 보단 list comprehension을 사용하는게 더 pythonic하다는 의견이 주류인 것 같다.
https://www.artima.com/weblogs/viewpost.jsp?thread=98196
[python] Comprehension, Generator / iterator VS iterable / itertools

 

lambda

```python
lambda args : returns
```

람다식은 `` filter, map, eval``같은 larger expression에 끼워서(inline) 사용하는 경우 가독성을 높여준다.

 

복잡한 상황에서는 명확한 ``py def``를 사용하는 편이 가독성이 더 좋다.

그리고 이런 식으로 람다식을 변수에 할당해서 쓰는 것은 지양해야 한다. (PEP8)

```py

sum = lambda a, b: a+b       # No

def sum(a, b): return a+b    # Yes

```

 

람다식을 사용하면 filter를 사용할 때 만들어야 하는 조건 함수를 대체할 수 있다.

```py

print(list(filter(lambda x: x > 0, [1, -3, 2, 0, -5, 6])))

```

자바 8에서의 람다식과 비슷하지만 함수형 인터페이스를 구현할 필요가 없다는 점이 편리하고 반복문을 사용할 수 없는 eval 등에 사용할 수 있다.

 

map / filter / reduce

filter와 map은 다음 세가지를 사용해 대체할 수 있다.
넘파이를 사용한다면 당연히 브로드캐스트를 사용하는게 좋으나 넘파이를 사용하지 않는다면 뭘 선택할지는 본인 마음인 듯.
단순 리스트 순회같은 경우 함수형을 사용하는 것이 가독성에 도움이 됨
  • numpy 브로드캐스트
  • list comprehension
  • generator
 

filter(function, iterable)

iterable에서 항목을 하나씩 function에 넘겨 return값이 true인 경우만 추출한다. 

필터를 사용하면 반복문을 사용해 순회하며 비교해야 하는 작업을 간단히 처리할 수 있다.

즉 function에는 조건역할을 하는 function이 들어가야 한다. ( ``py return expr`` )

* 이렇게 ``py True/False``를 반환하는 함수를 predicate(술어)라고 한다.

 

리스트에서 양수만 추출해서 리스트로 만드는 작업을 필터로 처리한 예다.

```py

def positive(x):

    return x > 0

 

print(list(filter(positive, [1, -3, 2, 0, -5, 6])))

```

filter 함수는 filter object를 반환하므로, 이를 list()로 묶어 list로 만들어야 사용할 수 있다.

 

map(function, iterable)

iterable에서 각각의 원소에 대해 function을 적용한 결과를 묶어서 리턴해준다. 

filter와 비슷하다고 생각할 수 있겠지만, filter는 function에 넘겨 수행한 결과가 True인 iterable의 항목을 추출하는 것이기 때문에 결과값을 추출하는 map과는 완전히 다르다.

 

또한 function이 조건함수여야만 하는 것은 아니다.

```py

print(list(map(lambda x: x*2, [1, 2, 3, 4, -1, -2, -5, -10])))

=>[2, 4, 6, 8, -2, -4, -10, -20]

```

 

filter의 경우 x*2를 입력하면 x*2의 결과가 항상 참이기 때문에 원래 리스트를 반환한다.

map을 filter처럼 사용하면 다음과 같이 ``py True/False``가 반환된다.

```py

print(list(map(lambda x: x>0, [1, 2, 3, 4, -1, -2, -5, -10])))

=>[True, True, True, True, False, False, False, False]

```

 

filter와 map을 조합해서 사용하기

```py

>>> list(map(lambda x: x*2, filter(lambda x: x>0, [1, 2, 3, 4, -1, -2, -3, -4])))

[2, 4, 6, 8]

```
 

reduce

reduce는 내장 함수가 아니다... import 해주어야 함.
```python
from functools import reduce
reduce(집계 함수, 순회 가능한 데이터[, 초기값])
```
*** 보통 reduce를 사용해야 하는 경우라면 list comprehension이 더 깔끔한 경우가 많다.
 

flatMap (custom)

  • 파이썬에서는 기본적으로 flatMap을 지원하지 않아서, 직접 정의해서 사용해야 함.
  • flatten2 방법은 list comp. 사용해서 자체 문법만으로 해결할 수 있어 간결하다는 장점.
  • flatten 방법은 iter 요소를 사용해서 지연 평가 가능하다는 장점 (테스트는 안해봤는데 아마 될 것 같다.)

```python

from itertools import chain

def flatten(iterable):

    return chain.from_iterable(iterable)

 

def flatten2(iterable):

    return [j for i in iterable for j in i]

 

def flatMap(func, iterable):

    return flatten(map(func, iterable))

```

 

파이썬 map filter reduce의 단점은...ㅠ

```python
# python
result_list = list( \
    map(..., \
    filter(..., \ 
    x_list.items()
    )))
```
```java
# java
result_list = x_list
    .filter(...)
    .map(...)
```

자바나 다른 언어 같은 경우는 위에서부터 필터 걸리고 맵 걸리고... 이런 식으로 위에서부터 데이터 처리 흐름 대로 읽어나갈 수 있는데

파이썬은 밑에서부터 list가 있고 그 다음 필터를 할거고... 그 다음 맵을 하고... 그 다음 리스트로 만든다. 로 읽어야 함.

 

코드는 위에서 부터 읽는게 편하기 때문에... 이런게 참 불편하다.

그래서 그냥 파이썬에서는

```python

t1 = filter(..., x_list.items())

t2 = map(..., t1)

result_list = list(t2)

```

 

차라리 이렇게 쓰는게 낫지 않을지...

 

https://github.com/EntilZha/PyFunctional#simple-example  라이브러리를 쓰면 chaining이 가능하긴 하다.