Um MapSet é uma coleção de valores únicos, que representa conjuntos em Elixir. Ele pode conter valores de qualquer tipo, sem noção de ordem.
Repare que o módulo Set também existe, mas está obsoleto em favor de MapSet.
Você pode criar conjuntos usando MapSet.new/0, MapSet.new/1 e MapSet.new/2, e transformá-los em listas usando MapSet.to_list/1.
MapSet.new()
# => MapSet.new([])
MapSet.new([2, 3, 3, 3, 1, 1, 2, "hello"])
# => MapSet.new([1, 2, 3, "hello"])
MapSet.new([2, 3, 3, 3, 1, 1, 2], fn n -> 10 * n end)
# => MapSet.new([10, 20, 30])
[2, 3, 3, 3, 1, 1, 2] |> MapSet.new() |> MapSet.to_list()
# => [1, 2, 3]
Repare que, como os MapSets não têm noção de ordem, não há garantia de que MapSet.to_list/1 retorne uma lista ordenada.
Você pode adicionar ou remover elementos com MapSet.put/2 e MapSet.delete/2.
Você pode consultar o conteúdo de um conjunto com as funções MapSet.size/1, MapSet.member?/2 e comparar conjuntos com MapSet.equal?/2, MapSet.subset?/2 e MapSet.disjoint?/2.
a = MapSet.new([1, 10])
b = MapSet.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
MapSet.size(b)
# => 10
MapSet.member?(a, 10)
# => true
MapSet.subset?(a, b)
# => true
MapSet.disjoint?(a, b)
# => false
MapSets podem ser combinados com MapSet.union/2, MapSet.intersection/2, MapSet.difference/2 e MapSet.symmetric_difference/2.
a = MapSet.new([1, 10, 100])
b = MapSet.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
MapSet.union(a, b)
# => MapSet.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100])
MapSet.intersection(a, b)
# => MapSet.new([1, 10])
MapSet.difference(a, b)
# => MapSet.new([100])
MapSet.difference(b, a)
# => MapSet.new([2, 3, 4, 5, 6, 7, 8, 9])
MapSet.symmetric_difference(b, a)
# => MapSet.new([2, 3, 4, 5, 6, 7, 8, 9, 100])
Você pode filtrar e particionar conjuntos com MapSet.filter/2, MapSet.reject/2 e MapSet.split_with/2.
a = MapSet.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
even = fn n -> rem(n, 2) == 0 end
MapSet.filter(a, even)
# => MapSet.new([2, 4, 6, 8, 10])
MapSet.reject(a, even)
# => MapSet.new([1, 3, 5, 7, 9])
MapSet.split_with(a, even)
# => {MapSet.new([2, 4, 6, 8, 10]), MapSet.new([1, 3, 5, 7, 9])}
Sua nostalgia pelas cartas Blorkemon™️ não dá sinal de diminuir. Você até voltou a colecioná-las e está trazendo seus amigos para junto de você.
Neste exercício, uma coleção de cartas é representada por um MapSet, já que cartas duplicadas não importam quando o seu objetivo é conseguir todas as cartas existentes.
Você quer muito que seus amigos entrem na sua loucura por Blorkemon™️, e a melhor forma é dar o pontapé inicial na coleção deles dando a cada um uma carta.
Implemente GottaSnatchEmAll.new_collection, que transforma uma carta em uma coleção.
GottaSnatchEmAll.new_collection("Newthree")
# => MapSet.new(["Newthree"])
Assim que você tem uma coleção, ela ganha vida própria e precisa crescer.
Implemente GottaSnatchEmAll.add_card, que recebe uma carta e uma coleção e retorna uma tupla com dois valores: um Boolean que indica se a carta já estava na coleção e a coleção com a carta adicionada.
GottaSnatchEmAll.add_card("Scientuna", MapSet.new(["Newthree"]))
# => {false, MapSet.new(["Newthree", "Scientuna"])}
Agora que seus amigos estão loucos por Blorkemon™️ de novo, você pode usar isso para aumentar a sua própria coleção trocando cartas.
Nem toda troca vale a pena ou é sequer possível. Você não pode trocar uma carta que não tem, e não deve trocar uma carta por outra que você já tem.
Implemente GottaSnatchEmAll.trade_card, que recebe duas cartas a trocar (a sua e a deles) e a sua coleção atual.
O valor de retorno é uma tupla de dois valores: um Boolean que diz se a troca é possível e vale a pena, e a coleção com que você ficaria se fizesse a troca (mesmo que ela não seja realmente possível).
GottaSnatchEmAll.trade_card("Scientuna", "Newthree", MapSet.new(["Scientuna"]))
# => {true, MapSet.new(["Newthree"])}
Você encontra um velho estoque de cartas em um mercado de pulgas. Você precisa ordenar as cartas e remover as duplicadas para comparar a lista com a sua coleção.
Implemente GottaSnatchEmAll.remove_duplicates, que ordena uma lista de cartas e retorna uma lista de cartas únicas e ordenadas.
GottaSnatchEmAll.remove_duplicates(["Newthree", "Newthree", "Newthree", "Scientuna"])
# => ["Newthree", "Scientuna"]
Hora de se sentir bem com a sua coleção.
Implemente GottaSnatchEmAll.extra_cards, que recebe a sua coleção e outra coleção qualquer e retorna o número de cartas que a outra coleção não tem.
GottaSnatchEmAll.extra_cards(MapSet.new(["Scientuna"]), MapSet.new(["Newthree", "Scientuna"]))
# => 0
Você e seus amigos entusiastas de Blorkemon™️ se reúnem e se perguntam quais cartas são as mais comuns.
Implemente GottaSnatchEmAll.boring_cards, que recebe uma lista de coleções e retorna uma lista ordenada das cartas que todas as coleções têm.
GottaSnatchEmAll.boring_cards([MapSet.new(["Scientuna"]), MapSet.new(["Newthree", "Scientuna"])])
# => ["Scientuna"]
Você e seus amigos, juntos, têm todas as cartas Blorkemon™️?
Implemente GottaSnatchEmAll.total_cards, que recebe uma lista de coleções e retorna o número total de cartas diferentes em todas as coleções.
GottaSnatchEmAll.total_cards([MapSet.new(["Scientuna"]), MapSet.new(["Newthree", "Scientuna"])])
# => 2
Seu sobrinho vai visitar você em breve, e você quer impressioná-lo. Crianças gostam de coisas brilhantes, né? As cartas Blorkemon™️ podem ser brilhantes!
Implemente GottaSnatchEmAll.split_shiny_cards, que recebe uma coleção e retorna uma tupla com duas listas de cartas ordenadas: uma com todas as cartas que começam com "Shiny" e outra com as demais cartas.
GottaSnatchEmAll.split_shiny_cards(MapSet.new(["Newthree", "Scientuna", "Shiny Scientuna"]))
# => {["Shiny Scientuna"], ["Newthree", "Scientuna"]}
Crie sua conta no Exercism para aprender e dominar Elixir com 58 conceitos168 exercícios e mentoria humana de verdade, tudo de graça.