상세 컨텐츠

본문 제목

map, lambda, zip, filter, reduce의 사용

Python

by techbard 2024. 12. 26. 06:33

본문

반응형

 

# Anonymous function and Lambda Expression

# def func(args):
#   return ret_val
#
# func = landa arg: ret_val

def f(x):
    return x - 1

print(f(3))
print(type(f))

ld_f = lambda x: x - 1

print(ld_f(3))
print(type(ld_f))

def last_char(s):
    return s[-1]

print(last_char('hello'))

ld_f2 = lambda s: s[-1]
print(ld_f2('hello'))

# 결과
2
<class 'function'>
2
<class 'function'>
o
o

 

### 람다 사용
"""
1. 아규먼트는 제한 없이 사용 가능, 단 평가식은 한 개만
2. 함수 객체가 쓰이는 곳이면 대용 가능 (람다는 함수 객체를 반환)
"""
def main():
    IsEvenOrOdd = \
    lambda n : "Even number" if n % 2 == 0 else "Odd number"

    print(IsEvenOrOdd(19))
    print(IsEvenOrOdd(20))

if __name__ == '__main__':
    main()

#결과
Odd number
Even number
### 람다 평가식의 활용
def main():
    choice_nums = \
    lambda s : ''.join([n for n in s if n.isdigit()])
    print(choice_nums('apple101'))

    print('\t')

    find_sum = \
    lambda s : sum([int(n) for n in str(s)])
    print(find_sum('101'))

if __name__ == '__main__':
    main()

#결과
101
	
2
### 함수에 람다 사용
def main():
    l = ['1', '2', '9', '0', '-1', '-2']
    print('Sorted numerically:', sorted(l, key=lambda n : int(n)))
    print('Filtered positive even numbers:', \
    list(filter(lambda n : (int(n) % 2 == 0 and int(n) > 0), l)))
    print('Operation on each item using lambda and map:', \
    list(map(lambda s : str(int(s) + 1), l)))

if __name__ == '__main__':
    main()

#결과
Sorted numerically: ['-2', '-1', '0', '1', '2', '9']
Filtered positive even numbers: ['2']
Operation on each item using lambda and map: ['2', '3', '10', '1', '0', '-1']

 

# A map is a function.
# It takes a sequence as its second input and (==> nums)
# it takes a function as its first input. (==> lambda)
# 첫 번째 인자가 함수명 전달인데,
# 다른 함수를 부르는 대신 람다 함수를 생성해 던졌다.

nums = [2, 5, 9]

ret = map((lambda x : x*2), nums)
print(list(ret))

# 결과
[4, 10, 18]

 

# Use map to produce a new list called abbrevs_upper that contains all the same 
# strings in upper case.
#
# abbrevs_upper = map(<transformer, abbrevs)
# The transformer is the hard part.
# Remember that the transformer has to be a function
# that function has to take one string as input
# and return the capitalization version of that string.

abbrevs = ["usa", "esp", "chn", "jpn", "mex", "can", "rus", "rsa", "jam"]
abbrevs_upper = map((lambda n : n.upper()), abbrevs)
print(list(abbrevs_upper))

# or
def transformer(st):
    return st.upper()

abbrevs_upper2 = map(transformer, abbrevs)
print(list(abbrevs_upper2))

# 결과
['USA', 'ESP', 'CHN', 'JPN', 'MEX', 'CAN', 'RUS', 'RSA', 'JAM']
['USA', 'ESP', 'CHN', 'JPN', 'MEX', 'CAN', 'RUS', 'RSA', 'JAM']

 

### map의 사용예 (지정된 함수로 시퀀스 객체를 처리)

def main():
    nums = 5

    even_result = list(map(mymod, range(nums)))
    ds = dict(zip(range(nums), even_result))
    print('Is even? =>', ds)

    pass


def mymod(n):
    if n % 2 == 0:
        return True
    else:
        return False

if __name__ == '__main__':
    main()

# 결과
Is even? => {0: True, 1: False, 2: True, 3: False, 4: True}

 

 

### 리스스의 star 개수를 읽어 index, len(star) dict 생성
import random

max_star_len = 10
def main():
    ls = []
    d = {}
    for i in range(10):
        ls.append('*' * random.randint(0, max_star_len))

    ### for - enum을 통한 첨자 할당
    for i, l in enumerate(ls):
        d[i] = len(ls[i])

    print(ls)
    print(d)

    print('\t')

    ### map, zip을 통한 묶음 dict 생성
    l = list(map(len, ls))
    d = dict(zip(range(max_star_len), l))

    print(ls)
    print(d)

if __name__ == '__main__':
    main()
 
 #결과
 ['**********', '**********', '', '*********', '***', '********', '***', '****', '*******', '*']
{0: 10, 1: 10, 2: 0, 3: 9, 4: 3, 5: 8, 6: 3, 7: 4, 8: 7, 9: 1}
	
['**********', '**********', '', '*********', '***', '********', '***', '****', '*******', '*']
{0: 10, 1: 10, 2: 0, 3: 9, 4: 3, 5: 8, 6: 3, 7: 4, 8: 7, 9: 1}

 

### map 클래스에 원하는 객체 타입을 지정해 변환
def main():

    m = map(str, [1, 2, 3])
    ls = list(m)

    print(ls)
    print(type(ls[0]))

    print('\t')

    s = map(int, ['1', '2', '3'])
    li = list(s)

    print(li)
    print(type(li[0]))

if __name__ == '__main__':
    main()
 
 #결과
 ['1', '2', '3']
<class 'str'>
	
[1, 2, 3]
<class 'int'>

 

# 클래스에 range 객체도 던질 수 있다.

m = map(str, range(1, 11))

s = ''.join(m)

print(type(s), "s: {}".format(s))

 

# 결과

<class 'str'> s: 12345678910

 

# map, lambda 혼용

ls = list(range(1, 6))

lm = map(lambda x: x+1, map(int, ls))

print(list(lm))

 

# 결과

[2, 3, 4, 5, 6]

 

 

### list comprehension과 zip의 사용
### 두 개의 쌍 중에서 더 큰 값을 리턴

def main():
    lx = [5, 2, 3]
    ly = [1, 2, 4]

    ls = [max(x, y) for x, y in zip(lx, ly)]
    print(ls)

if __name__ == '__main__':
    main()

#결과
[5, 2, 4]
### 람다를 이용 짝 중 큰수를 리턴
def main():
    a = [5, 2, 3]
    b = [1, 2, 4]

    r = map(lambda pair : max(pair), zip(a, b))
    print(list(r))

if __name__ == '__main__':
    main()

#결과
[5, 2, 4]
### 람다, max 함수를 이용해 두 개의 쌍 중에서 더 큰 값을 리턴
def main():
    l1 = [1, 3, 5, 7]
    l2 = [2, 4, 6, 8]

    l = list(map(lambda x, y : max(x, y), l1, l2))
    print(l)

if __name__ == '__main__':
    main()

#결과
[2, 4, 6, 8]

 

# Another common processing pattern,
# we've seen before is to filter a sequence.
# You start with some items and you end up with fewer of them.

def keep_evens(nums: list) -> list:
    ret_list = []
    for num in nums:
        if num % 2 == 0:
            ret_list.append(num)
    return ret_list

print(keep_evens([1, 2, 3, 4, 5]))

filtered = filter((lambda x : x % 2 == 0), [1, 2, 3, 4, 5])
print(list(filtered))

# 결과
[2, 4]
[2, 4]

 

### filter
### 이터러블에서 특정 조건의 함수 결과가 True인 것만 추림

def getEvens(n):
    if n % 2 ==0:
        return True

def main():
    r1 = list(filter(getEvens, [1, 2, 3, 4, 5]))
    print('r1:', r1)
    print('\t')

    r2 = list(filter(lambda n : n % 2 == 0, [1, 2, 3, 4, 5]))
    print('r2:', r2)
    print('\t')

    r3 = list(filter(lambda n : True if n % 2 == 0 else False, [1, 2, 3, 4, 5]))
    print('r3:', r3)

if __name__ == '__main__':
    main()

#결과
r1: [2, 4]
	
r2: [2, 4]
	
r3: [2, 4]

 

### reduce의 결과는 single value
import functools

def main():
    ls = [1, 2, 3]
    r = functools.reduce(lambda x, y: x + y, ls)
    print(type(r))
    print(r)

if __name__ == '__main__':
    main()

#결과
<class 'int'>
6

 

### reduce 이터러블을 받아 연산 후에 연산 결과의 누적을 리턴
### pair에 대한 연산을 전체 이터러블로 확대할 때 사용
### 명시적인 loop 구현 없이 이터러블 처리
### 단일값만 리턴 (객체 리턴 X)
import functools

def main():
    data = [{'name' : 'a', 'age' : 1},
    {'name' : 'b', 'age' : 2}, {'name' : 'c', 'age' : 3}]

    # 초기값이 없으면 에러 발생
    r = functools.reduce(lambda x, y : x + y['age'], data, 0)

    print(r)

if __name__ == '__main__':
    main()

#결과
6

 

### reduce가 for-loop 없이 비슷한 효과를 낸다.
### 이런 특성을 이용해 문자열 합치기
import functools

def main():
    ls = ['a', 'p', 'p', 'l', 'e']
    s = functools.reduce(lambda x, y : x + y, ls)
    print(type(s))
    print(s)

if __name__ == '__main__':
    main()

#결과
<class 'str'>
apple

 

### flattening a list of lists into a single list
import functools

def main():
    list_2D = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    r = functools.reduce(lambda x, y : x + y, list_2D)
    print(type(r))
    print(r)

if __name__ == '__main__':
    main()

#결과
<class 'list'>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
### for-loop 없이 reduce를 사용해 함수 적용
import functools

def main():
    ls = [11, 9, 12, 15, 7, 13]

    r = functools.reduce(lambda x, y : min(x, y), ls)
    print(type(r))
    print('min:', r)

    r = functools.reduce(lambda x, y : max(x, y), ls)
    print(type(r))
    print('max:', r)

if __name__ == '__main__':
    main()

#결과
<class 'int'>
min: 7
<class 'int'>
max: 15

 

 

# ord(c, /)

# Return the Unicode code point for a one-character string.

o = (list(map(ord, 'hello')))

print(list(map(chr, o)))

 

# 결과

['h', 'e', 'l', 'l', 'o']

 

 

 

### 문자열 리스트를 받아 그중 가장 긴 문자열 출력

def makePairs(ls):
    return dict(zip(ls, map(len, ls)))

def main():
    pairs, ret = [], []
    inList = ['aaa', 'bb', 'cccc', 'd', 'eeeeeeeeee']
    pairs = makePairs(inList)
    maxlen = max(pairs.values())

    for k, v in pairs.items():
        if v == maxlen:
            ret.append(k)

    print(ret)

    pass

if __name__ == '__main__':
    main()

# 결과

['eeeeeeeeee']

 

# 함수를 람다로 변경

pairs, result = [], []
inList = ['aaa', 'bb', 'cccc', 'd', 'eeeeeeeeee']
pairs = dict(zip(inList, map(lambda x: len(x), inList)))
max_length = max(pairs.values())
for k, v in pairs.items():
    if v == max_length:
        result.append(k)

print(pairs)

max_length_key = ''.join(result)
print(max_length_key + ':' + str(pairs.get(max_length_key)))

# 결과
{'aaa': 3, 'bb': 2, 'cccc': 4, 'd': 1, 'eeeeeeeeee': 10}
eeeeeeeeee:10

 

# 약간 더 간결하게 수정

# data format
# {'string': length} -> {'aa': 2}

results = []
inList = ['aaa', 'bb', 'cccc', 'd', 'eeeee', 'fffff']
pairs = dict(zip(inList, map(lambda x: len(x), inList)))
max_length = max(pairs.values())
for k, v in pairs.items():
    if v == max_length:
        results.append(k)

print('==========')
for max_length_key in results:
    print(max_length_key + ':' + str(max_length))
print('==========')

# 결과
==========
eeeee:5
fffff:5
==========

 

# for-loop 안 쓰고 filter로 조건에 맞는 요소 추출

results = []
inList = ['aaa', 'bb', 'cccc', 'd', 'eeeee', 'fffff']
pairs = dict(zip(inList, map(lambda x: len(x), inList)))
# {'aaa': 3, 'bb': 2, 'cccc': 4, 'd': 1, 'eeeee': 5, 'fffff': 5}
# dict_items([('aaa', 3), ('bb', 2), ('cccc', 4), ('d', 1), ('eeeee', 5), ('fffff', 5)])

max_length = max(pairs.values())
results = list(filter(lambda pair: pair[1] == max_length, pairs.items()))
print(results)

# 결과
[('eeeee', 5), ('fffff', 5)]

 

# 다른 결과도 함께 출력

max_results, min_results, avg_results = [], [], []
inList = ['a', 'bb', 'ccc', 'dd', 'eeeee', 'fffff']
pairs = dict(zip(inList, map(lambda x: len(x), inList)))

max_length = max(pairs.values())
min_length = min(pairs.values())
avg_length = int(sum(pairs.values()) / len(inList))

max_results = list(filter(lambda pair: pair[1] == max_length, pairs.items()))
min_results = list(filter(lambda pair: pair[1] == min_length, pairs.items()))
avg_results = list(filter(lambda pair: pair[1] == avg_length, pairs.items()))

print('max len: ' + str(max_results))
print('min len: ' + str(min_results))
print('avg len: ' + str(avg_results))

# 결과
max len: [('eeeee', 5), ('fffff', 5)]
min len: [('a', 1)]
avg len: [('ccc', 3)]

 

 

def lenFunc(s):
    return len(s)

x = map(lenFunc, ('apple', 'banana', 'cherry'))

print(list(x))

y = map(lambda x: len(x), ('apple', 'banana', 'cherry'))
print(list(y))

# 결과
[5, 6, 6]
[5, 6, 6]

 

l1 = [3, 4, 5]
l2 = [1, 2, 3]

ls = list(zip(l1, l2))
print(ls)

def zip_func(lst1: list, lst2: list) -> list:
    ret = []
    for idx in range(len(lst1)):
        ret.append((lst1[idx], lst2[idx]))
    return ret

zipped = zip_func(l1, l2)
print(zipped)

print("")
print(f"Are equal built-in zip and zip_func the same? {ls == zipped}")

# 결과
[(3, 1), (4, 2), (5, 3)]
[(3, 1), (4, 2), (5, 3)]

Are equal built-in zip and zip_func the same? True

 

ls1 = [1, 2, 3]
ls2 = [4, 5, 6]

ret1 = [sum(two_pairs) for two_pairs in list(zip(ls1, ls2))]
print(ret1)

ret2 = [n1 + n2 for (n1, n2) in list(zip(ls1, ls2))]
print(ret2)

print("")
print(f"Are equal ret1 and ret2 the same? {ret1 == ret2}")

# 결과
[5, 7, 9]
[5, 7, 9]

Are equal ret1 and ret2 the same? True

 

# The zip Function

l1 = [1, 2, 3]
l2 = ['a', 'b', 'c']

zipped = list(zip(l1, l2))
print(zipped)

zipped[-1] = 99, 'z'
print(zipped)

# main use-case

names = ['Niko', 'Ara', 'Kily']
group = [1, 2, 3]
score = [88, 99, 57]

for name, grp, sc in zip(names, group, score):
    print(f"{name} from group {group} scored {sc}")

# 결과
[(1, 'a'), (2, 'b'), (3, 'c')]
[(1, 'a'), (2, 'b'), (99, 'z')]
Niko from group [1, 2, 3] scored 88
Ara from group [1, 2, 3] scored 99
Kily from group [1, 2, 3] scored 57

 

# Practical use-case of zip Function
# - Finding the lowest score

golfer1 = [5, 7, 4, 3, 8, 9]
golfer2 = [4, 8, 4, 4, 7, 4]
golfer3 = [6, 5, 4, 4, 4, 6]

lowest = []
for scores in zip(golfer1, golfer2, golfer3):
    lowest.append(min(scores))

print(f"lowest scores: {lowest}")

win_count = {g: 0 for g in ('golfer1', 'golfer2', 'golfer3')}

# 개별 골퍼가 승리한 횟수 카운트
for idx in range(len(lowest)):
    if lowest[idx] == golfer1[idx]:
        win_count['golfer1'] += 1
    if lowest[idx] == golfer2[idx]:
        win_count['golfer2'] += 1
    if lowest[idx] == golfer3[idx]:
        win_count['golfer3'] += 1

print(f"win count of all golfers => {win_count}")

# 결과
lowest scores: [4, 5, 4, 3, 4, 4]
win count of all golfers => {'golfer1': 2, 'golfer2': 3, 'golfer3': 3}

 

# zip(seq1, seq2, ...)
num_first: list[int] = [1, 2, 3, 4, 5]
num_second: list[int] = [10, 20, 30, 40, 50]
num_third: list[int] = [100, 200, 300, 400, 500]

d = {n: [] for n in num_first} 

nums_zip:zip = zip(num_first, num_second, num_third)

for f, s, t in nums_zip:
    d[f] = [s, t]

print(d)

# 결과
{1: [10, 100], 2: [20, 200], 3: [30, 300], 4: [40, 400], 5: [50, 500]}

 

x = (lambda x, y: x+y) (1, 2)

print(x)

# Output
3

 

import itertools

seq1 = ["A", "B", "C", "D", "E", "F"]
seq2 = [1, 2, 3, 4]
seq3 = "xyz"

result = itertools.zip_longest(seq1, seq2, seq3, fillvalue="-")
print(list(result))

# Output:
[('A', 1, 'x'), ('B', 2, 'y'), ('C', 3, 'z'), ('D', 4, '-'), ('E', '-', '-'), ('F', '-', '-')]
반응형

관련글 더보기

댓글 영역