프로그래밍/PYTHON

python - map(), filter(), reduce() usage

aiemag 2020. 10. 27. 21:50
반응형

 

iterable object를 python 답게 사용할 수 있는 map(), filter(), reduce() 삼형제에 대해 알아보겠습니다.

 

 

 


 


map

map은 지정된 함수로 반복 가능한 요소를 일괄 처리해주는 기능을 합니다.

 

현실에서의 예를 들자면, 엄마가 "자 콩나물 100개가 있으니깐 머리의 콩껍질을 다 까놔"라고 심부름을 시키신 경우가 되겠습니다. (요즘에는 먹기좋게 마트에서 다 손질되어 나오지만 저 어렸을 때는 콩나물을 직접 시루에서 키워서 콩껍질이 붙어 있는채로 팔았습니다. -_-)

불쌍한 아들은 모든 콩나물 머리에 대해서 콩껍질을 까려고 했습니다. 아래와 같이 for 문으로 콩나물 1번 부터 10번 콩나물 하나씩 말이죠.

 

bs_list = list(range(1,101))

for i in range(1, len(bs_list)):
    bs_list[i] = str(bs_list[i])

str() 함수를 이용해서 integer 타입의 콩나물의 콩껍질을 모두 벗겼습니다. 콩나물이 100개라서 망정이지 100만개 정도면 집을 나가야 할지도 모르겠습니다..


그러던 어느날, 엄마가 콩나물 국밥집 장사를 하셔야겠다며 정말?로 1만개의 콩나물 껍질을 다 까달라고 아들에게 부탁하셨습니다. 

 

울고만 있는 아들에게 python의 지니(map)가 나타났네요. 아주 신통방통한 녀석입니다.

 

bs_list = list(range(1,1000001))

bs_list = list(map(str, bs_list))

짜잔, 한번에 모든 콩나의 껍질을 다 까서 str 타입으로 변환하였습니다.

 

 

아래의 code를 보시면 더욱 직관적으로 와 닿을 것 같습니다.

 

아래의 test_map1~3 usage를 보시면 iterable 객체의 일괄 작업을 map을 통하여 간결하게 처리할 수 있습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/bin/python3
 
def test_map1():
    a = ["1""2""3""4"]
    b = list(map(int, a))
    print(b)
 
 
def test_map2():
    a = list(map(strrange(10)))
    print(a)
 
 
def test_map3():
    
    def convert(data):
        return int(data)
 
    a = ["1""2""3""4"]
    b = map(convert, a)
    print(b)
    print(list(b))
 
 
def main():
    test_map1()
    test_map2()
    test_map3()
 
 
if __name__ == "__main__":
    main()
cs

 

테스트 함수 설명

 

1. test_map1()

map을 이용하여 int함수로 character 원소로 이루어진 a list를 일괄 integer형으로 변환하도록 합니다.

 

2. test_map2()

역시 map을 이용하여 str함수로 range(10)로 생성된 iterator 객체를 일괄 character형으로 변환하도록 합니다.

 

3. test_map3()

이번엔 직접 만든 convert 함수를 사용해 보겠습니다.

위의 두 예와 마찬가지로 map을 이용하여 convert함수로 character 원소로 이루어진 a list를 일괄 integer형으로 변환하도록 합니다.

 

이때 map 객체가 반환하는 map 객체는 iterator이며, 값을 확인하기 위해 list 형으로 바꾸어 출력하도록 하였습니다.

 

결과는 한번 예상해 보시고 직접 실행하여 출력 결과를 확인해 보시기 바랍니다^^b

 

출력 결과

 

 

 

 


filter

map이 iterable한 객체에 대해 원하는 function으로 일괄 변형한 값으로 mapping 시켜주는 역할이라면

 

filter는 iterable한 객체에서 원하는 function에서 허용하는 element만 filtering을 해주는 역할을 합니다.

 

filter(function, iterable) 형태로 사용할 수 있으며  sample code는 다음과 같습니다.

 

3 line의 names list에 대해 test_filter1번 부터 4번까지 모두 동일한 결과를 만들어 주는데 하나씩 살펴보겠습니다.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

#!/usr/bin/python3

 

names = ["jack""jay""robert""john"]

 

def test_filter1():

 

    def starts_with_j(x):

        return x.startswith('j')

 

    rst = filter(starts_with_j, names)

    print(list(rst))

 

 

def test_filter2():

    

    def starts_with(c):

 

        def func(x):

            return x.startswith(c)

 

        return func 

 

    rst = filter(starts_with('j'), names)

    print(list(rst))

 

 

def test_filter3():

 

    print(list(filter(lambda x: x.startswith('j'), names)))

 

 

def test_filter4():

    

    def starts_with_j(x):

        return x.startswith('j')

 

    # using list comprehension

    rst = [x for x in names if starts_with_j(x)]

    print(rst)

 

 

def main():

    test_filter1()

    test_filter2()

    test_filter3()

    test_filter4()

 

 

if __name__ == "__main__":

    main()

Colored by Color Scripter

cs

 

테스트 함수 설명

 

1. test_filter1()

filter의 기본 형태입니다. starts_with_j() 함수를 이용하여 'j'로 시작하는 element만 return 합니다.

 

2. test_filter2()

test_filter1번과 비슷한 형태이지만 closure(다른 포스팅에서 다룸) 를 이용하여 특정 문자를 직접 지정할 수 있도록 처리하였습니다.

 

3. test_filter3()

lambda식을 이용하여 최대한 짧게 code를 작성하였습니다.

 

4. test_filter4()

list comprehension 형태를 이용한 방법입니다.

 

한번 직접 실행해서 결과도 확인해보세요^^b

 

출력 결과

 

 

 


reduce

reduce 는 python의 built-in 함수는 아니며 functools library에서 제공하는 함수입니다.

 

map()이 일괄 계산, filter()가 일괄 filter를 제공한다면 reduce()는 모든 element들에 대해 순서대로 누적 처리를 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/python3
 
from functools import reduce
 
def test_reduce1():
    rst = reduce(lambda x, y: x+y, range(1,11))
    print(rst)
 
 
def test_reduce2():
    rst = reduce(lambda x, y: x+y, range(1,11), 10)
    print(rst)
 
 
def test_reduce3():
    rst = reduce(lambda x, y: x if x > y else y, range(1,11))
    print(rst)
 
 
def main():
    test_reduce1()   
    test_reduce2()   
    test_reduce3()   
 
 
if __name__ == "__main__":
    main()
cs

 

테스트 함수 설명

 

1. test_reduce1()

lamda 함수는 x와 y가 주어지면 둘을 더해서 return 합니다. 

range(1, 11)는 1부터 10을 가리키는 iterable object 입니다.

reduce를 통해 lamda 함수에서 정의된 대로 초깃 값 0과 첫째 값 1을 더해서 1을 return 합니다.

이어서 return 된 1과 둘째 값 2를 더해서 3을 return 합니다. 

이런식으로 쭉 lamda 함수를 적용하면 최종 55 값이 나오게 됩니다.

 

2. test_reduce2()

reduce 함수를 사용할 때 초깃 값을 지정해 줄수도 있습니다. 여기서는 10으로 지정하였습니다.

 

3. test_reduce3()

lamda 함수를 조건문으로 넣어 최종 가장 큰 값을 return 하게도 할 수 있습니다.

 

출력 결과

반응형

'프로그래밍 > PYTHON' 카테고리의 다른 글

python - Iterable, Iterator  (0) 2021.02.03
python - Decorator  (4) 2021.01.22
python - Closure  (0) 2020.11.03
python - global, nonlocal keyword  (0) 2020.10.25
python 어렵지 않아요  (6) 2020.06.08