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}]
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,
color: "Ochre Red",
base_color: "red"
}
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"}}
# ]
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"}}
# ]
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}}
# ]
Sign up to Exercism to learn and master Elixir with 57 concepts, 159 exercises, and real human mentoring, all for free.