Tracks
/
Elixir
Elixir
/
Exercises
/
Boutique Suggestions
Boutique Suggestions

Boutique Suggestions

Learning Exercise

Introduction

List Comprehensions

Comprehensions provide a facility for transforming Enumerables easily and declaratively.

To declare a very simple comprehension, we can use the for keyword followed by a generator and a do-block which creates the new values from the enumerated values.

for n <- [0, 1, 2, 3], do: n + 1
# => [1, 2, 3, 4]

Comprehensions can also have filters. Values that do not pass the filter are removed from the final list:

for n <- [0, 1, 2, 3], n > 1, do: n + 1
# => [3, 4]

We can declare more complicated comprehensions over several lines:

for {atom, number} <- [a: 1, b: 2, c: 3, d: 4],
    rem(number, 2) == 0 do
  atom
end

# => [:b, :d]

A cartesian product can be created using multiple generators. That means that each value generated by the first generator will be paired once with each value generated by the second generator:

for x <- [0, 1],
    y <- [0, 1] do
  {x, y}
end

# => [{0, 0}, {0, 1}, {1, 0}, {1, 1}]

Instructions

Your work at the online fashion boutique store continues. You come up with the idea for a website feature where an outfit is suggested to the user. While you want to give lots of suggestions, you don't want to give bad suggestions, so you decide to use a list comprehension since you can easily generate outfit combinations, then filter them by some criteria.

Clothing items are stored as a map:

%{
  item_name: "Descriptive Name",
  price: 99.00,
  base_color: "red"
}

1. Suggest a combination

Implement get_combinations/3 to take a list of tops, a list of bottoms, and keyword list of options. For now, set options to default to an empty keyword list. The function should return the cartesian product of the lists.

tops = [
  %{item_name: "Dress shirt"},
  %{item_name: "Casual shirt"}
]

bottoms = [
  %{item_name: "Jeans"},
  %{item_name: "Dress trousers"}
]

BoutiqueSuggestions.get_combinations(tops, bottoms)
# => [
#      {%{item_name: "Dress shirt"}, %{item_name: "Jeans"}},
#      {%{item_name: "Dress shirt"}, %{item_name: "Dress trousers"}},
#      {%{item_name: "Casual shirt"}, %{item_name: "Jeans"}},
#      {%{item_name: "Casual shirt"}, %{item_name: "Dress trousers"}}
#    ]

2. Filter out clashing outfits

Each piece of clothing has a :base_color field, use this field to filter out all combinations where the top and the bottom have the same base color.

tops = [
  %{item_name: "Dress shirt", base_color: "blue"},
  %{item_name: "Casual shirt", base_color: "black"}
]

bottoms = [
  %{item_name: "Jeans", base_color: "blue"},
  %{item_name: "Dress trousers", base_color: "black"}
]

BoutiqueSuggestions.get_combinations(tops, bottoms)
# => [
#      {%{item_name: "Dress shirt", base_color: "blue"},
#       %{item_name: "Dress trousers", base_color: "black"}},
#      {%{item_name: "Casual shirt", base_color: "black"},
#       %{item_name: "Jeans", base_color: "blue"}}
#    ]

3. Filter by combination price

Each piece of clothing has a :price field associated with it. While you want to give lots of suggestions, you want to be able to provide users an opportunity to select a price within their budget. From the keyword list of options, use :maximum_price to filter out combinations where the price of the top and bottom exceed the maximum price.

If no maximum_price is specified, the default should be 100.00

tops = [
  %{item_name: "Dress shirt", base_color: "blue", price: 35},
  %{item_name: "Casual shirt", base_color: "black", price: 20}
]

bottoms = [
  %{item_name: "Jeans", base_color: "blue", price: 30},
  %{item_name: "Dress trousers", base_color: "black", price: 75}
]

BoutiqueSuggestions.get_combinations(tops, bottoms, maximum_price: 50)
# => [
#      {%{item_name: "Casual shirt", base_color: "black", price: 20},
#       %{item_name: "Jeans", base_color: "blue", price: 30}}
#    ]
Edit via GitHub The link opens in a new window or tab
Elixir Exercism

Ready to start Boutique Suggestions?

Sign up to Exercism to learn and master Elixir with 57 concepts, 158 exercises, and real human mentoring, all for free.