상세 컨텐츠

본문 제목

List Comprehension, filter, map, lambda 사용법

Python

by techbard 2024. 12. 2. 15:17

본문

반응형

 

 

# List comprehension
#
# It just make creating lists much more efficient and
# reduce drastically the amount of code you need to create simple lists.
# They become nearly impossible to live without.

numbers: list[int] = [1, 2, 3]
numbers_lc = [num for num in range(1, 4)]

print(numbers)
print(numbers_lc)
print(f"Is the numbers equal to numbers_lc? : {numbers == numbers_lc}")

doubled: list[int] = []
for num in numbers:
    doubled.append(num*2)

doubled_lc: list[int] = [num*2 for num in numbers]
print(f"Is the doubled equal to doubled_lc? : {doubled == doubled}")

# 결과
[1, 2, 3]
[1, 2, 3]
Is the numbers equal to numbers_lc? : True
Is the doubled equal to doubled_lc? : True

 

names: list[str] = ['Mario', 'James', 'Luigi', 'John']
j_names_lc: list[str] = [name for name in names if name.lower().startswith('j')]
print(j_names_lc)

numbers: list[int] = [1, 2, 4, 6, 7, 10]
even_numbers_lc: list[int] = [even for even in numbers if even % 2 == 0]
print(even_numbers_lc)

# 결과
['James', 'John']
[2, 4, 6, 10]

 

# List Comprehensions Example
words = ['list', 'comprehension', 'can', 'be', 'confusing']

# Getting the length of each word
words_dict = {word: len(word) for word in words}
print(words_dict)

# Selecting the last character of each string
words_last_char = {word: word[-1] for word in words}
print(words_last_char)

# Rolling a dice some number of times
import random

rnd_num_rolling = [random.randint(1, 6) for n in range(10)]
print(f"rolloing: {rnd_num_rolling}")
rnd_num_rolling = [random.randint(1, 6) for n in range(10)]
print(f"rolloing: {rnd_num_rolling}")

# 결과
{'list': 4, 'comprehension': 13, 'can': 3, 'be': 2, 'confusing': 9}
{'list': 't', 'comprehension': 'n', 'can': 'n', 'be': 'e', 'confusing': 'g'}
rolloing: [2, 1, 6, 4, 4, 6, 3, 6, 6, 2]
rolloing: [4, 1, 1, 4, 5, 6, 3, 4, 6, 6]

 

# Conditional list comprehensions

# Ex - squaring odd integers

squared_odd_nums = []

for num in range(1, 11):
    if num % 2 == 1:
        squared_odd_nums.append(num ** 2)
print(squared_odd_nums)

squared_odd_nums_lc = [num ** 2 for num in range(1, 11) if num % 2 == 1]
print(squared_odd_nums_lc)

# 결과
[1, 9, 25, 49, 81]
[1, 9, 25, 49, 81]

 

# list comprehension 사용

es = [1, 2, 3]

new_list = [e for e in es if e % 2 == 0]

print(f'org. list: {es}')
print(f'even nums: {new_list}')

# 결과
org. list: [1, 2, 3]
even nums: [2]

 

# Find all words in a sentence with more than 3 letters
sentence = "Python is my favorite programming language in the world"
more_than_3leteers = {word: len(word) for word in sentence.split() if len(word) > 3}
print(more_than_3leteers)

# Extract words that start with "t"
starts_with_t = [word for word in sentence.split() if word.startswith("t")]
print(starts_with_t)

# 결과
{'Python': 6, 'favorite': 8, 'programming': 11, 'language': 8, 'world': 5}
['the']

 

# Ternary operator in list comprehension

even_or_odd = {n: "even" if n % 2 == 0 else "odd" for n in range(10)}
print(even_or_odd)

# 결과
{0: 'even', 1: 'odd', 2: 'even', 3: 'odd', 4: 'even', 5: 'odd', 6: 'even', 7: 'odd', 8: 'even', 9: 'odd'}

 

# Complex list comprehensions

complex_lc = [n**2 if n % 2 == 0 else n**3 for n in range(10) if 6 < n < 10]
complex_lc.sort()
print(complex_lc)

normal_for_loop = set()
for n in range(10):
    if 6 < n < 10:
        if n % 2 == 0:
            normal_for_loop.add(n ** 2)
        else:
            normal_for_loop.add(n ** 3)
print(sorted(normal_for_loop))

# 결과
[64, 343, 729]
[64, 343, 729]

 

# Nested for-loops within List Comprehensions
times_table = [f'x={x+1}, y={y+1}' for x in range(3) for y in range (3)]
print(times_table)

# 결과
['x=1, y=1', 'x=1, y=2', 'x=1, y=3', 'x=2, y=1', 'x=2, y=2', 'x=2, y=3', 'x=3, y=1', 'x=3, y=2', 'x=3, y=3']

 

# lookup_table에 있는 것만 제외하고 리스트 생성

lookup_table = [0, 0, 7]
check_list = [1, 2, 3, 4, 1, 0, 1, 2, 3, 0, 7]
ret = [c for c in check_list if c not in lookup_table]
print(ret)

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

 

lookup_table = [0, 0, 7]
matching_list = [1, 2, 1, 3, 1, 0, 4, 0, 3, 5, 5, 7, 0, 0, 7]

# lookup에 있는 요소는 모두 제외
def all_lookup_filter(lookup, matching):
    return [m for m in matching if m not in lookup]

# lookup에 있는 요소 하나만 제외하고 나머지는 유지
def one_lookup_filter(lookup, matching):
    ret = []
    for m in matching:
        if m in lookup:
            lookup.remove(m)
            continue
        else:
            ret.append(m)
    return ret

print(f'lookup_table: {lookup_table}')
print(f'matching_list: {matching_list}')
print('')

print('all_lookup_filter =>')
print(all_lookup_filter(lookup_table, matching_list))

print('one_lookup_filter =>')
print(one_lookup_filter(lookup_table, matching_list))

# 결과
lookup_table: [0, 0, 7]
matching_list: [1, 2, 1, 3, 1, 0, 4, 0, 3, 5, 5, 7, 0, 0, 7]

all_lookup_filter =>
[1, 2, 1, 3, 1, 4, 3, 5, 5]
one_lookup_filter =>
[1, 2, 1, 3, 1, 4, 3, 5, 5, 0, 0, 7]

 

# lookup에 있는 요소 하나만 제외하고 나머지는 유지
# lookup_table을 하나씩 제거하면서 비교하는 또 다른 버전
# global로 지정하면 리스트 컴프리헨션 내의 리스트를 변경할 수 있음 (약간 억지)

global glk
glk = [0, 0, 7]

def one_lookup_filter2(lookup, matching):
    temp_ret = [lookup.remove(m) if m in lookup else m for m in matching]
    ret = [t for t in temp_ret if t != None]
    return ret

print('gloval_lookup_filter =>')
print(one_lookup_filter2(glk, matching_list))

# 결과
global_lookup_filter =>
[1, 2, 1, 3, 1, 4, 3, 5, 5, 0, 0, 7]

 

# List Comprehension과 map, filter의 적용

nums = [1, 2, 3]

lc_result = [n + 1 for n in nums]
print(lc_result)
print("=====")

# n + 1 == lambda n : n + 1

mp_result = map(lambda n : n + 1, nums)
print(list(mp_result))
print("=====")

# 여기까지 결과에서 다시 필터를 적용하려면

# 방법1)
ret1 = []
for n in lc_result:
    if n % 2 == 0:
        ret1.append(n)
print(ret1)
print("=====")

# 방법2) - the version using a list comprehension
ret2 = [n for n in lc_result if n % 2 == 0]
print(ret2)
print("-----")

# 방법3) - same filtration expression as part of the lambda function
ret3 = filter((lambda n : n % 2 == 0), lc_result)
print(list(ret3))
print("-----")

# 방법4)
# map, filter 함수를 두 번 적용해 같은 결과를 만듦
ret4 = filter(lambda n : n % 2 == 0, map((lambda n : n + 1), nums))
print(list(ret4))

# 결과
[2, 3, 4]
=====
[2, 3, 4]
=====
[2, 4]
=====
[2, 4]
-----
[2, 4]
-----
[2, 4]

 

# Nested Data Extraction
# List Comprehension and filter
tester = {'info': [{"name": "Lauren", 'class standing': 'Junior', 'major': "Information Science"}, 
{'name': 'Ayo', 'class standing': "Bachelor's", 'major': 'Information Science'}, 
{'name': 'Kathryn', 'class standing': 'Senior', 'major': 'Sociology'}, 
{'name': 'Nick', 'class standing': 'Junior', 'major': 'Computer Science'}, 
{'name': 'Gladys', 'class standing': 'Sophomore', 'major': 'History'}, 
{'name': 'Adam', 'major': 'Violin Performance', 'class standing': 'Senior'}]}

# best solution
keys = []
inner_list = tester['info']

for name_dict in inner_list:
    keys.append(name_dict['name'])

print(keys)
print("=====" * 10)
import json
print(json.dumps(inner_list, indent=2))

# my solution
keys = []
for person_list in tester.values():
    for name_dict in person_list:
        keys.append(name_dict['name'])

print(keys)
import json
print(json.dumps(person_list, indent=2))

print("")
print(f"inner_list equals person_list? {inner_list == person_list}")
print("")

# 최종 결과 내기 - 이름이 'a'로 시작하는 학생
print("===== f i n a l  r e s u l t =====")
keys = []
inner_list = tester['info']
startswith_a = [d['name'] for d in inner_list if d['name'][0] == 'A']
print(startswith_a)

# 결과
['Lauren', 'Ayo', 'Kathryn', 'Nick', 'Gladys', 'Adam']
==================================================
[
  {
    "name": "Lauren",
    "class standing": "Junior",
    "major": "Information Science"
  },
  {
    "name": "Ayo",
    "class standing": "Bachelor's",
    "major": "Information Science"
  },
  {
    "name": "Kathryn",
    "class standing": "Senior",
    "major": "Sociology"
  },
  {
    "name": "Nick",
    "class standing": "Junior",
    "major": "Computer Science"
  },
  {
    "name": "Gladys",
    "class standing": "Sophomore",
    "major": "History"
  },
  {
    "name": "Adam",
    "major": "Violin Performance",
    "class standing": "Senior"
  }
]
['Lauren', 'Ayo', 'Kathryn', 'Nick', 'Gladys', 'Adam']
[
  {
    "name": "Lauren",
    "class standing": "Junior",
    "major": "Information Science"
  },
  {
    "name": "Ayo",
    "class standing": "Bachelor's",
    "major": "Information Science"
  },
  {
    "name": "Kathryn",
    "class standing": "Senior",
    "major": "Sociology"
  },
  {
    "name": "Nick",
    "class standing": "Junior",
    "major": "Computer Science"
  },
  {
    "name": "Gladys",
    "class standing": "Sophomore",
    "major": "History"
  },
  {
    "name": "Adam",
    "major": "Violin Performance",
    "class standing": "Senior"
  }
]

inner_list equals person_list? True

===== f i n a l  r e s u l t =====
['Ayo', 'Adam']

 

# Write a function called longlengths that 
# returns the lengths of those strings that 
# have at least 4 characters. Try it with a list comprehension.
 
strs = ['aaa', 'bbb', 'cccc', 'ddddd']

ret_using_lc = [len(x) for x in strs if len(x) >= 4]
print(ret_using_lc)

ret_using_filter = map(len, filter((lambda x : len(x) >= 4), strs))
print(list(ret_using_filter))

# 결과
[4, 5]
[4, 5]

 

# Flatten List 1
info = [['1', 10], ['2', 20], ['3', 30]]

flatten = []
for i in info:
    flatten.append(i[0])
    flatten.append(i[1])
print(flatten)

# Flatten List 2
info = [['1', 10], ['2', 20], ['3', 30]]

flatten = [e for inner in info for e in inner]
print(flatten)

# 결과
['1', 10, '2', 20, '3', 30]
['1', 10, '2', 20, '3', 30]

 

# flatten the list
two_dl = [['a', 1], ['b', 2], ['c', 3], ['d'], ['e', 4, 5]]
flattened_list = [e for one_dl in two_dl for e in one_dl]
print(flattened_list)

# 결과
['a', 1, 'b', 2, 'c', 3, 'd', 'e', 4, 5]

 

# Squaring an item in a list

my_list = [5, 8, -9, 0, 3]

rst = list(map(lambda n: n**2, my_list))
print(rst)

# This is the exact same as a list comprehension
rst_lc = [n**2 for n in my_list]
print(rst_lc)

# 결과
[25, 64, 81, 0, 9]
[25, 64, 81, 0, 9]

 

# Filter for values greater than 4
my_list = [5, 8, -9, 0, 3]

rst = list(filter(lambda n: n > 4, my_list))
print(rst)

rst_lc = [n for n in my_list if n > 4]
print(rst_lc)

# 결과
[5, 8]
[5, 8]

 

# 설명

[] 문법은 리스트 생성에 사용

집합과 원소를 표기할 때는 주로 elements, element 와 같은 식으로 네이밍한다.

따라서 위의 예제에서는 elems가 집합, elem이 원소를 의미한다.
하지만 가독성이 좋지 못하므로, 명백한 부분에만 사용 권장 (나중에 다시 보면 바로 이해하기 힘듦)
특히 if - else 구문을 사용하려면 순서가 앞으로 오는 표기법을 사용하므로 매우 혼란스러움

 

[elem for elem in elems if elem > 2] -> elems 집합 중에서

[elem for elem in elems if elem > 2] -> 하나씩 꺼내 elem 원소에 넣고

[elem for elem in elems if elem > 2] -> 꺼낸 elem 원소가 조건을 만족하면

[elem for elem in elems if elem > 2] -> 조건을 만족한 elem 원소를 가지고

[elem for elem in elems if elem > 2] -> 리스트에 넣는다.

 

 

 

 

 

 

# filter 내장함수 사용

def above_two(n):

if n > 2:

return n

else:    # 이하 구문은 없어도 함수를 빠져나갈 때 None이 리턴되지만, filter 함수가 참/거짓을 판단조건으로 한다는 점을 보이기 위해 일부러 넣었다.

return None

 

print('filter: ' + str(list(filter(above_two, elems))))

 

# 결과

filter: [3]

 

# 설명

def funcName(n): -> filter 함수에 끼워넣을 사용자 함수 생성 (filter가 작동하려면 사용자 함수는 참/거짓을 리턴해야 한다.)

...

 

filter(funcName, sequence) -> funcName은 이미 정의한 사용자 함수 명, sequence는 시퀀스 형 데이터를 넣는다.

filter(above_two, elems) -> elems 집합에서 원소를 하나씩 꺼내

filter(above_two, elems) -> above_two 함수에 넣는다. 이 함수에서는 처리를 한 결과를 리턴한다.

filter(above_two, elems) -> elems의 모든 원소에 대해서 above_two 함수에 던져 결과를 참인 원소만 모아 filter 객체를 생성한다.

 

list(filter(above_two, elems)) -> filter 객체를 리스트로 변환한다.

 

print('filter: ' + str(list(filter(above_two, elems)))) -> print 함수에서 스트링과 합치기 위해 다시 강제로 list 형을 string 형으로 변환한다.

 

# lambda와 filter 사용

print('filter w/ lambda: ' + str(list(filter(lambda n : n > 2, elems))))

 
# 결과
filter w/ lambda: [3]

 

# 설명

filter(lambda n : n > 2, elems)) -> 람다 함수는 함수 이름이 없고 표현식만으로 이루어진 함수로 이 람다 함수를 누군가가 부를때 n에 값이 들어간다. 람다 함수 내부에서는 누군가가 던진 값을 : 뒤의 처리를 해서 리턴한다.

 

# map 내장함수 사용

 

def plus_one(n):

return n + 1

 

print('map func: ' + str(list(map(plus_one, elems))))

 

# 결과

map func: [2, 3, 4]

 

# 설명

map(plus_one, elems) -> elems 집합 내의 요소 하나씩 꺼내

map(plus_one, elems) -> plus_one 함수에 던져 반환된 값을 모아

map(plus_one, elems) -> map 객체를 만든다.

 

# lambda와 map 사용

print('map w/ lambda: ' + str(list(map(lambda n : n + 1, elems))))

 
# 결과
map w/ lambda: [2, 3, 4]

 

# 설명

위의 모든 설명과 마찬가지로

 

map 내장 함수의 첫번째 인자로 들어가는 함수이름에 이름 없는 lambda 함수가 들어갔다.

 

# list comprehension, map, lambda 사용하기

 

filtered_with_map = map(lambda elem : elem + 1, [elem for elem in elems if elem % 2 == 0])

 

# 결과

[3, 5]

 

# 설명

먼저 map 내장 함수의 syntax를 살펴보자.

 

map(함수, 시퀸스 유형 데이터)

 

즉, lambda는 형태는 표현식이지만 함수 대용으로 쓰는 이름 없는 함수라고 했으므로 map() 내장 함수의 첫번째 인자로 줄 수 있다.

 

map(lambda elem : elem + 1,

 

다시 map 내장 함수의 두번째 인자를 생각해 보자.

 

여기는 시퀸스 유형의 데이터 라고 했으므로 앞서 list comprehension을 쓸 수 있다. 왜냐하면 결과로 리스트를 리턴하기 때문이다.

 

map(lambda elem : elem + 1, [elem for elem in elems if elem % 2 == 0])

 

결과적으로

 

1) map() 내장 함수의 두 번째 인자를 통해 집합을 만들고

2) 그 집합의 원소 하나 하나를

3) map() 내장 함수의 첫번째 인자의 함수에 넣어

4) 함수에서 리턴된 결과를 모아 map 객체를 만들어 반환한다.

 

라고 동작을 정리할 수 있다.

 

# dict comprehension

 

ds = dict(one=1, two=2, three=3)

 

ld = ['%s = %d' % (k, v) for k, v in ds.items() if v > 1]

 

print(ld)

 

# 결과

['three = 3', 'two = 2']

 

# for - loop, list comprehension, filter 함수, if - else 구문 사용
# 같은 동작을 하는 다른 구현

my_string = 'Sammy'

#1
result1 = []
for letter in my_string:
    if letter == 'a':
        continue
    else:
        result1.append(letter)
print(f'#1 {result1}')

#2
result2 = [x for x in my_string if x != 'a']
print(f'#2 {result2}')

#3
result3 = list(filter(lambda x: x != 'a', my_string))
print(f'#3 {result3}')

result4 = [x if x != 'a' else None for x in my_string]
result4.remove(None)
print(f'#4 {result4}')

# 결과
#1 ['S', 'm', 'm', 'y']
#2 ['S', 'm', 'm', 'y']
#3 ['S', 'm', 'm', 'y']
#4 ['S', 'm', 'm', 'y']

 

## map 함수의 이해

def is_even(num):
    if num % 2 == 0:
        return True
    else:
        return False

def create_check_even_pairs(num_list):
    check_result = []

##    for n in num_list:
##        check_result.append(is_even(n))
## 아래와 같이 이터러블에 map을 적용하는 것도 깔끔하다.

##    for n in map(is_even, num_list):
##        check_result.append(n)
## 그런데 사실, for - loop을 쓸 필요도 없다.
## map 함수가 이터러블만큰 함수를 호출해 준다.

##    check_result = list(map(is_even, num_list))
##    return dict(zip(num_list, check_result))
## 그런데 또 사실, dict 결과를 반환할거면
## list 변환도 필요없다.

## map을 사용할 때 함수를 실행하는 것이 아닌 함수 자체를
## 넘기는 것이므로, is_even() 로 넣지 않는다.
##    return dict(zip(num_list, map(is_even, num_list)))

## is_even() 함수가 한 줄짜리 이므로 람다식으로도 가능하다.
## 즉, is_even() 함수는 불필요하다.
    return dict(zip(num_list, map(lambda x: x % 2 == 0, num_list)))

my_nums = [1, 2, 3, 4, 5]

ret = create_check_even_pairs(my_nums)
print(ret)

# 결과
{1: False, 2: True, 3: False, 4: True, 5: False}

 

## 단어가 나오는 개수 포함해 사전 생성 (map, dict 사용)

fruits = ['apple', 'banana', 'cherry', 'durian', 'banana', 'apple', 'banana']

one_d = dict()
for f in fruits:
    one_d[f] = 0

two_d = dict.fromkeys(fruits, 0)

# 2 ways of init the dict
print(one_d)
print(two_d)
print('*' * 50)

# 2 ways of set the dict
for f in one_d.keys():
    amount = fruits.count(f)
    one_d[f] = amount

two_d = dict(zip(fruits, map(lambda x : fruits.count(x), fruits)))

print(one_d)
print(two_d)

# 결과
{'apple': 0, 'banana': 0, 'cherry': 0, 'durian': 0}
{'apple': 0, 'banana': 0, 'cherry': 0, 'durian': 0}
**************************************************
{'apple': 2, 'banana': 3, 'cherry': 1, 'durian': 1}
{'apple': 2, 'banana': 3, 'cherry': 1, 'durian': 1}

 

# Flatten uneven nested list

nested_list = [1, 2, [3, 4, 5]]

# list 아닌 요소만 골라냄
filtered_list = [e for e in nested_list if type(e) is not list]
print(filtered_list)

# 그러나, even하지 않은 중첩 리스트를 풀어야 하면 문제가 복잡해 진다.
# 리스트 컴프리핸션으로는 생각해 낼 수 없어 for-loop를 사용

rst = []

for inner in nested_list:
    if type(inner) is list:
        rst.extend(inner)
    else:
        rst.append(inner)
print(rst)

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

 

# nested list and want to flatten it.
# MS copilot이 알려준 같은 결과의 최적화 버전

lol = [1, [2], 3, [4, 5]]

flat_list = [item for sublist in lol for item in (sublist if type(sublist) is list else [sublist])]
print(flat_list)

# Output: [1, 2, 3, 4, 5]

 

# 중요한 표현식이므로 다시 한 번 작성함
all_nested_list = [['1', 10], ['2', 20], ['3', 30]]
flat_list = [item for sublist in all_nested_list for item in sublist]
print(flat_list)

uneven_nested_list = [1, [2, 3], ['4', 5]]
flatten_list = [item for sublist in uneven_nested_list for item in (sublist if isinstance(sublist, list) else [sublist])]
print(flatten_list)

# Output
['1', 10, '2', 20, '3', 30]
[1, 2, 3, '4', 5]

 

# 리스트 풀어 쓰기 로직은 유지하고 다른 방식으로 구현하기
data = [1, 2, [3, 4], 5, [6, 7, 8], [9, 10]]

idx = 0
flat_list = []

while idx < len(data):
    if isinstance(data[idx], list):
        for item in data[idx]:
            flat_list.append(item)
    else:
        flat_list.append(data[idx])
    idx += 1

print(flat_list)

# 결과
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

 

# Nested for-loops within List Comprehensions (triple)

word_created = []
for x in 'bm':
    for y in 'ae':
        for z in 'dt':
            word_created.append(x + y + z)
print(word_created)

word_created_lc = [x + y + z for x in 'bm' for y in 'ae' for z in 'dt']
print(word_created_lc)

# 결과
['bad', 'bat', 'bed', 'bet', 'mad', 'mat', 'med', 'met']
['bad', 'bat', 'bed', 'bet', 'mad', 'mat', 'med', 'met']

 

# What is a Comprehension?
# - Comprehensions are a concise syntax for creating lists, sets and dictionaries from
# - any kind of sequence, set and mapping.
# - Generally comprehensions are referred to as list comprehensions, set comprehensions
# and dictionary comprehensions base upon the result type.
# - Conditions can be applied to comprehensions limiting the items from the original sequence,
# set, and mapping which are added to the new list, set or dictionary.
# - A lazy form of comprehension is a generator object and it can be passed to functions
# which expect to receive a generator.
# - Comprehensions enable concise yet easy to understand code to be written.

# - Many comprehensions could be erwritten with map, filter, reduce and lambdas but such
# implementations can be slower and harder to understand.

# 일반버전
squares_fl: list[int] = []
for n in range(1, 11):
    squares_fl.append(n**2)
print(f"{squares_fl=}")

# map 함수를 쓴 버전 (느리고 읽기 어려움)
squares_mp = list(map(lambda n: n**2, range(1, 11)))
print(f"{squares_mp=}")

# 컴프리핸션을 사용한 가장 나은 버전
squares_lc = [n**2 for n in range(1, 11)]
print(f"{squares_lc=}")

# 결과
squares_fl=[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
squares_mp=[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
squares_lc=[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

 

# List/Dict Comprehensions, tuple unpacking
cart: list[list[str, float, int]] = \
[['coffee', 7.99, 2],
 ['Bread', 2.99, 1],
 ['Apple', 0.99, 2],
 ['Milk', 4.99, 1],
 ['Cola', 1.99, 4]]

item_prices: list[float] = [item[1] for item in cart]
print(f"{item_prices=}")

cart_item_total_prices: dict[str, float] = {item: (qty * price) for (item, price, qty) in cart}
print(f"{cart_item_total_prices=}")

# tax 10% (included in price)
cart_item_tax: dict[str,float] = {item: round(total_price - (total_price/1.1), 2) for (item, total_price) in cart_item_total_prices.items()}
print(f"{cart_item_tax=}")

# 결과
item_prices=[7.99, 2.99, 0.99, 4.99, 1.99]
cart_item_total_prices={'coffee': 15.98, 'Bread': 2.99, 'Apple': 1.98, 'Milk': 4.99, 'Cola': 7.96}
cart_item_tax={'coffee': 1.45, 'Bread': 0.27, 'Apple': 0.18, 'Milk': 0.45, 'Cola': 0.72}

 

# Random chr creation
import random

random_letters: list[str] = [chr(random.randint(ord('a'), ord('z'))) for _ in range(10)]
print(f"{random_letters}")

# 결과
['o', 'm', 't', 'j', 's', 'q', 'x', 'l', 'q', 'b']

 

# Adding to Conditions to Comprehensions
person_marks: list[str, int] = \
    [['Bob',    78],
    ['Sally',   85],
    ['John',    93]]

marks_avg: float = round(sum([mark for (person, mark) in person_marks]) / len(person_marks), 2)
print(f"{marks_avg=}")

d: dict[str, list[int, str]] = {person: [mark, 'above avg or equal' if mark >= marks_avg else 'below avg'] for (person, mark) in person_marks}
print(f"person marks & eval: {d}")

# 결과
marks_avg=85.33
person marks & eval: {'Bob': [78, 'below avg'], 'Sally': [85, 'below avg'], 'John': [93, 'above avg or equal']}

 

# 리스트 플랫
matrix: list[list[int]] = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat: list[int] = [n for row in matrix for n in row]
print(f"{flat=}")

squared: list[list[int]] = [[n**2 for n in row] for row in matrix]
print(f"{squared=}")

# if - then list comprehension
nums: list[int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

x1 = [n for n in nums if n > 4 and n % 2 ==0]
print(x1)
x2 = [n for n in nums if n > 4 if n % 2 == 0]
print(x2)
assert x1 == x2

# 결과
flat=[1, 2, 3, 4, 5, 6, 7, 8, 9]
squared=[[1, 4, 9], [16, 25, 36], [49, 64, 81]]
[6, 8, 10]
[6, 8, 10]

 

# 조합을 list comprehension으로 구현
colors: list[str] = ['red', 'green', 'blue']
sizes: list[str] = ['S', 'M', 'L']
combinations = [(color, size) for color in colors for size in sizes]
print(f"{combinations=}")

# flat list 기억을 위해 다시 구현
nested_list: list[list[int, int]] = [[1, 2], [3, 4], [5, 6]]
flattened = [item for sublist in nested_list for item in sublist]
print(f"{flattened=}")

# 결과
combinations=[('red', 'S'), ('red', 'M'), ('red', 'L'), ('green', 'S'), ('green', 'M'), ('green', 'L'), ('blue', 'S'), ('blue', 'M'), ('blue', 'L')]
flattened=[1, 2, 3, 4, 5, 6]

 

import random

# Sample dataset: a list of dictionaries with customer purchases
customer_purchases = [
    {
        "customer_id": f"CUST-{i}",
        "purchase_amount": random.randint(50, 500),
        "items": [f"item{random.randint(1, 10)}" for _ in range(random.randint(1, 5))]
    }
    for i in range(1, 31)
]

# Task 1: Filter high-value purchases (over $300)
high_value_purchases = []
for purchase in customer_purchases:
    if purchase["purchase_amount"] > 300:
        high_value_purchases.append(purchase)

# Task 2: Calculate total spending per customer
customer_spending = {}
for purchase in customer_purchases:
    customer_id = purchase["customer_id"]
    if customer_id in customer_spending:
        customer_spending[customer_id] += purchase["purchase_amount"]
    else:
        customer_spending[customer_id] = purchase["purchase_amount"]

# Task 3: Aggregate all items bought by customers
all_items = []
for purchase in customer_purchases:
    for item in purchase["items"]:
        all_items.append(item)

# Task 4: Calculate the average purchase amount using a loop
total_amount = 0
for purchase in customer_purchases:
    total_amount += purchase["purchase_amount"]
average_purchase = total_amount / len(customer_purchases)

# Display Results
print("High-Value Purchases:", high_value_purchases)
print("Customer Spending:", customer_spending)
print("All Items Purchased:", all_items)
print("Average Purchase Amount:", average_purchase)

# 결과
High-Value Purchases: [{'customer_id': 'CUST-2', 'purchase_amount': 411, 'items': ['item5', 'item7', 'item4', 'item9']}, {'customer_id': 'CUST-5', 'purchase_amount': 428, 'items': ['item8', 'item9', 'item6', 'item9']}, {'customer_id': 'CUST-8', 'purchase_amount': 339, 'items': ['item4', 'item1', 'item2', 'item8']}, {'customer_id': 'CUST-9', 'purchase_amount': 484, 'items': ['item3', 'item8', 'item6', 'item10']}, {'customer_id': 'CUST-10', 'purchase_amount': 356, 'items': ['item8', 'item6', 'item6', 'item5']}, {'customer_id': 'CUST-11', 'purchase_amount': 478, 'items': ['item1', 'item2', 'item6']}, {'customer_id': 'CUST-14', 'purchase_amount': 312, 'items': ['item9', 'item1', 'item3', 'item10']}, {'customer_id': 'CUST-21', 'purchase_amount': 415, 'items': ['item1', 'item1', 'item10', 'item1']}, {'customer_id': 'CUST-24', 'purchase_amount': 309, 'items': ['item1', 'item6']}, {'customer_id': 'CUST-26', 'purchase_amount': 447, 'items': ['item7']}]
Customer Spending: {'CUST-1': 158, 'CUST-2': 411, 'CUST-3': 257, 'CUST-4': 283, 'CUST-5': 428, 'CUST-6': 156, 'CUST-7': 93, 'CUST-8': 339, 'CUST-9': 484, 'CUST-10': 356, 'CUST-11': 478, 'CUST-12': 122, 'CUST-13': 159, 'CUST-14': 312, 'CUST-15': 121, 'CUST-16': 113, 'CUST-17': 280, 'CUST-18': 61, 'CUST-19': 223, 'CUST-20': 244, 'CUST-21': 415, 'CUST-22': 250, 'CUST-23': 166, 'CUST-24': 309, 'CUST-25': 87, 'CUST-26': 447, 'CUST-27': 220, 'CUST-28': 236, 'CUST-29': 291, 'CUST-30': 103}
All Items Purchased: ['item8', 'item1', 'item5', 'item5', 'item5', 'item7', 'item4', 'item9', 'item5', 'item7', 'item4', 'item8', 'item9', 'item6', 'item9', 'item7', 'item6', 'item9', 'item4', 'item8', 'item10', 'item4', 'item1', 'item2', 'item8', 'item3', 'item8', 'item6', 'item10', 'item8', 'item6', 'item6', 'item5', 'item1', 'item2', 'item6', 'item9', 'item4', 'item10', 'item7', 'item9', 'item10', 'item9', 'item1', 'item3', 'item10', 'item9', 'item10', 'item6', 'item6', 'item5', 'item4', 'item10', 'item4', 'item7', 'item10', 'item6', 'item2', 'item10', 'item1', 'item5', 'item9', 'item1', 'item1', 'item10', 'item1', 'item1', 'item9', 'item5', 'item1', 'item6', 'item6', 'item6', 'item2', 'item7', 'item6', 'item4', 'item7', 'item3', 'item10', 'item9', 'item2', 'item2', 'item5', 'item3', 'item10']

 

# iter(callable, sentinel)
# callable: 호출이 가능한 객체
# sentinel: 반복하다가 특정 값이 나오면 반복을 중단 / 반복을 감시하다가 특정 값이 나오면 반복을 끝내는 sentinel

# 문자열을 이터레이터로 변환
text: str = 'hello world!'

it = iter(text)
for _ in range(len(text)):
    print(next(it), end=' ')

# 호출 객체를 부르고, 중단점 설정
import random
from typing import Iterator

print("")
random_int_it: Iterator[int] = iter(lambda :random.randint(1, 10), 10)
# 10이 나올 때까지 반복

for i in random_int_it:
    print(i, end=' ')

# 결과
h e l l o   w o r l d ! 
4 6 2 9 4 4 3 9 3 8 8 2 3 6 2 4 6

 

#  비정형 데이터에서 정형 데이터만 골라내기
row = ['10/25/13', '08:24:00 AM', '29', '', '01:14:00 PM', '27']

def number_filter(row):
    try:
        float(row)
        return True
    except ValueError:
        return False

filtered = list(filter(number_filter, row))
print(f"filtered of len: {len(filtered)}")
print(filtered)

# 결과
filtered of len: 2
['29', '27']
반응형

관련글 더보기

댓글 영역