트랙
/
Elixir
Elixir
/
연습 문제
/
부티크 재고
부티크 재고

부티크 재고

학습 연습 문제

소개

Enum

Enum은 enumerable을 다루기 위한 여러 알고리즘을 제공하는 아주 유용한 모듈이에요. 정렬, 필터링, 그룹화, 개수 세기, 검색, 최솟값/최댓값 찾기 등 다양한 기능을 제공해요.

일반적으로 _enumerable_은 반복할 수 있는 모든 데이터, 즉 컬렉션을 말해요. Elixir에서 enumerable은 Enumerable 프로토콜을 구현하는 모든 데이터 타입이에요. 그중 가장 흔한 것은 배열과 맵이에요.

많은 Enum 함수는 함수를 인자로 받아요.

Enum.all?([1, 2, 3, 4, 5], fn x -> x > 3 end)
# => false

가장 흔히 쓰이는 Enum 함수는 map과 reduce예요.

map/2

Enum.map/2를 사용하면 enumerable의 모든 원소를 다른 원소로 바꿀 수 있어요. Enum.map/2의 두 번째 인자는 원래 원소를 받아서 그 대체값을 반환하는 함수예요.

reduce/3

Enum.reduce/3를 사용하면 enumerable 전체를 하나의 값으로 줄일 수 있어요. 이를 위해 _누산기_라는 특별한 변수를 사용해요. 누산기는 각 반복 사이에서 리듀스의 중간 상태를 담아 둬요.

Enum.reduce/3의 두 번째 인자는 누산기의 초깃값이에요. 세 번째 인자는 원소와 누산기를 받아서 누산기의 새 값을 반환하는 함수예요.

맵 다루기

맵을 Enum 함수와 함께 사용하면, 맵이 자동으로 2개의 {key, value} 튜플로 이루어진 배열로 변환돼요.

다시 맵으로 되돌리려면 Enum.into/2를 사용해요. Enum.into/2는 enumerable을 collectable로 변환하는 함수예요. 여기서 collectable은 Collectable 프로토콜을 구현하는 모든 데이터 구조를 말해요. Enum.reduce/3의 반대라고 생각하면 돼요.

Enum에는 Enum.into/3도 있어요. Enum.into/3은 Enum.into/2의 변형으로, enumerable을 collectable로 변환하는 동안 적용할 변환 함수를 받아요.

맵 매핑하기

맵에 변환(매핑)을 적용하기 위해 Enum.into/3이나 Enum.map/2에 Enum.into/2를 더해서 쓰는 대신, Map.new/2라는 전용 함수를 사용할 수도 있어요. 이 함수는 enumerable과 변환 함수를 받는다는 점에서 Enum.into/3과 똑같이 동작하지만, collectable을 고를 수 있게 하는 대신 항상 새로운 맵을 반환해요.

지침

온라인 패션 부티크를 운영하고 있어요. 곧 큰 연례 세일이 다가오니, 준비가 잘 됐는지 확인하려면 재고를 파악해야 해요.

재고의 상품 하나는 맵으로 표현하고, 재고 전체는 이런 맵의 배열이에요.

%{
  name: "White Shirt",
  price: 40,
  quantity_by_size: %{s: 3, m: 7, l: 8, xl: 4}
}

1. 가격순으로 상품 정렬하기

sort_by_price/1 함수를 구현해요. 이 함수는 재고를 받아서 상품 가격을 기준으로 오름차순으로 정렬한 결과를 반환해야 해요.

BoutiqueInventory.sort_by_price([
  %{price: 65, name: "Maxi Brown Dress", quantity_by_size: %{}},
  %{price: 50, name: "Red Short Skirt", quantity_by_size: %{}},
  %{price: 50, name: "Black Short Skirt", quantity_by_size: %{}},
  %{price: 20, name: "Bamboo Socks Cats", quantity_by_size: %{}}
])

# => [
#      %{price: 20, name: "Bamboo Socks Cats", quantity_by_size: %{}},
#      %{price: 50, name: "Red Short Skirt", quantity_by_size: %{}},
#      %{price: 50, name: "Black Short Skirt", quantity_by_size: %{}},
#      %{price: 65, name: "Maxi Brown Dress", price: 65, quantity_by_size: %{}}
#    ]

2. 가격이 없는 상품 모두 찾기

재고를 가격순으로 정렬하고 나니, 재고를 파악할 때 실수로 몇몇 상품의 가격을 채우지 않았다는 걸 알아차렸어요.

with_missing_price/1 함수를 구현해요. 이 함수는 재고를 받아서 가격이 없는 상품의 배열을 반환해야 해요.

BoutiqueInventory.with_missing_price([
  %{price: 40, name: "Black T-shirt", quantity_by_size: %{}},
  %{price: nil, name: "Denim Pants", quantity_by_size: %{}},
  %{price: nil, name: "Denim Skirt", quantity_by_size: %{}},
  %{price: 40, name: "Orange T-shirt", quantity_by_size: %{}}
])

# => [
#      %{price: nil, name: "Denim Pants", quantity_by_size: %{}},
#      %{price: nil, name: "Denim Skirt", quantity_by_size: %{}}
#    ]

3. 상품 이름 업데이트하기

일부 상품 이름에 더는 쓰고 싶지 않은 단어가 있다는 걸 알아차렸어요. 이제 그 단어가 들어간 상품 이름을 모두 업데이트해야 해요.

update_names/3 함수를 구현해요. 이 함수는 재고, 없애고 싶은 예전 단어, 대신 사용할 새 단어를 받아요. 그리고 이름이 바뀐 상품의 배열을 반환해야 해요.

BoutiqueInventory.update_names(
  [
    %{price: 40, name: "Black T-shirt", quantity_by_size: %{}},
    %{price: 70, name: "Denim Pants", quantity_by_size: %{}},
    %{price: 65, name: "Denim Skirt", quantity_by_size: %{}},
    %{price: 40, name: "Orange T-shirt", quantity_by_size: %{}}
  ],
  "T-shirt",
  "Tee"
)

# => [
#      %{price: 40, name: "Black Tee", quantity_by_size: %{}},
#      %{price: 70, name: "Denim Pants", quantity_by_size: %{}},
#      %{price: 65, name: "Denim Skirt", quantity_by_size: %{}},
#      %{price: 40, name: "Orange Tee", quantity_by_size: %{}}
#    ]

4. 상품 수량 늘리기

몇몇 상품이 특히 잘 팔려서 모든 사이즈를 더 주문했어요.

increase_quantity/2 함수를 구현해요. 이 함수는 상품 하나와 숫자 n을 받아서, 각 사이즈의 수량을 n만큼 늘린 상품을 반환해야 해요.

BoutiqueInventory.increase_quantity(
  %{
    name: "Polka Dot Skirt",
    price: 68,
    quantity_by_size: %{s: 3, m: 5, l: 3, xl: 4}
  },
  6
)

# => %{
#      name: "Polka Dot Skirt",
#      price: 68,
#      quantity_by_size: %{l: 9, m: 11, s: 9, xl: 10}
#    }

5. 상품의 총 수량 계산하기

창고에 공간이 얼마나 필요한지 알려면, 상품별로 전체 수량이 몇 개인지 알아야 해요.

total_quantity/1 함수를 구현해요. 이 함수는 상품 하나를 받아서, 사이즈에 상관없이 전체 조각이 몇 개인지 반환해야 해요.

BoutiqueInventory.total_quantity(%{
  name: "Red Shirt",
  price: 62,
  quantity_by_size: %{s: 3, m: 6, l: 5, xl: 2}
})

# => 16
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Elixir Exercism

부티크 재고 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Elixir 트랙을 개념 58개연습 문제 168개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.