Trilhas
/
Julia
Julia
/
Exercícios
/
Sugestões da boutique
Sugestões da boutique

Sugestões da boutique

Exercício de aprendizagem

Introdução

Quem já usou Python quase certamente já usou compreensões de listas, que são parte central da sintaxe do Python desde as primeiras versões.

Algo tão conveniente acaba, aos poucos, chegando a outras linguagens, inclusive Julia.

Para quem programa em Julia, as compreensões são uma opção, não uma necessidade, já que geralmente existem alternativas (broadcasting, funções de ordem superior etc.).

No entanto, uma compreensão muitas vezes oferece uma forma simples, legível e eficiente de construir um array. No fim, usá-las é uma questão de gosto pessoal, e de como você se sente em relação a Python versus linguagens funcionais.

A sintaxe é, em grande parte, uma cópia direta do Python, mas com extensões para arrays de dimensões maiores.

Uma única variável

Bem ao estilo Python, incluindo a cláusula if opcional.

julia> [x^2 for x in 1:3]
3-element Vector{Int64}:
 1
 4
 9
julia> [x^2 for x in 1:3 if isodd(x^2)]
2-element Vector{Int64}:
 1
 9

O formato da saída depende dos detalhes da compreensão: normalmente é igual ao da coleção de entrada em casos simples, mas é achatado para um Vector por uma cláusula if.

julia> m
2×3 Matrix{Int64}:
 1  2  3
 4  5  6
julia> [x^2 for x in m]
2×3 Matrix{Int64}:
  1   4   9
 16  25  36
julia> [x^2 for x in m if isodd(x^2)] 
3-element Vector{Int64}:
  1
 25
  9

Múltiplas variáveis, saída em Vector

Assim como em Python, podemos ter várias cláusulas for com variáveis diferentes, usando a mesma coleção de entrada ou coleções diferentes.

julia> [x * y for x in 1:3 for y in 4:6]
9-element Vector{Int64}:
  4
  5
  6
  8
 10
 12
 12
 15
 18
julia> [x * y for x in 1:3 for y in 4:6 if isodd(x * y)]
2-element Vector{Int64}:
  5
 15

Isso equivale a laços aninhados. A saída é unidimensional, mesmo com uma matriz na entrada.

julia> m
2×3 Matrix{Int64}:
 1  2  3
 4  5  6
julia> [x*y for x in m for y in m]
36-element Vector{Int64}:
  1
  4
  2
  5
(truncated output...)

Múltiplas variáveis, saída multidimensional

A seção anterior mostrou várias cláusulas for separadas apenas por espaços.

Nesta seção, há um único for e as variáveis são separadas por vírgulas.

julia> [(x, y) for x in 1:3, y in 4:6]
3×3 Matrix{Tuple{Int64, Int64}}:
 (1, 4)  (1, 5)  (1, 6)
 (2, 4)  (2, 5)  (2, 6)
 (3, 4)  (3, 5)  (3, 6)

Cada variável da compreensão cria uma nova dimensão na saída, com uma entrada para cada combinação possível das variáveis.

No exemplo acima, x aumenta descendo pelas linhas e y aumenta percorrendo as colunas. Dimensões maiores são possíveis, com os avisos de sempre sobre a legibilidade da saída.

Expressões geradoras

As seções anteriores focaram na saída em array, com a compreensão colocada entre colchetes [ ... ].

Quando os colchetes são substituídos por parênteses ( ... ), acontece algo diferente: obtemos uma generator expression, um iterador de avaliação preguiçosa que pode fornecer o próximo valor sob demanda.

julia> g = ((x, y) for x in 1:3, y in 4:6)
Base.Generator{Base.Iterators.ProductIterator{Tuple{UnitRange{Int64}, UnitRange{Int64}}}, var"#9#10"}(var"#9#10"(), Base.Iterators.ProductIterator{Tuple{UnitRange{Int64}, UnitRange{Int64}}}((1:3, 4:6)))
# Indexing fails with a generator, the entries don't exist yet
julia> g[1, 2]
ERROR: MethodError: no method matching getindex(::Base.Generator{Base.Iterators.ProductIterator{Tuple{UnitRange{…}, UnitRange{…}}}, var"#9#10"}, ::Int64, ::Int64)
# conversion to array
julia> collect(g)
3×3 Matrix{Tuple{Int64, Int64}}:
 (1, 4)  (1, 5)  (1, 6)
 (2, 4)  (2, 5)  (2, 6)
 (3, 4)  (3, 5)  (3, 6)
# generators are mainly designed for iteration
julia> [i * j for (i, j) in g]
3×3 Matrix{Int64}:
  4   5   6
  8  10  12
 12  15  18

Quando o resultado de uma compreensão é usado imediatamente em processamento posterior, um gerador pode economizar memória, evitando a necessidade de armazenar um array intermediário grande.

Um gerador usado como argumento de função não precisa de parênteses adicionais.

# inefficient
julia> v = [x^2 for x in 1:1e6];
julia> sum(v)
3.333338333335e17
# better - use a generator
julia> sum(x^2 for x in 1:1e6)
3.3333383333312755e17

A sintaxe do gerador é idêntica à das compreensões, a não ser pelos delimitadores que os envolvem.

Geradores também podem ser úteis em construtores de dicionário.

julia> Dict(x => x^2 for x in 1:5)
Dict{Int64, Int64} with 5 entries:
  5 => 25
  4 => 16
  2 => 4
  3 => 9
  1 => 1

Instruções

Você trabalha em uma loja de moda online. Você tem a ideia de criar um recurso no site em que looks são sugeridos ao usuário. Interessam os looks possíveis, seus preços e a eliminação das opções que não combinam.

Note

Embora possa haver diferentes formas de resolver os problemas a seguir, todos podem ser resolvidos com uma compreensão de lista.

1. Crie uma peça de roupa

Implemente clothingitem() para receber dois Tuples, um de categories e outro das respectivas qualities. A função deve retornar um Dict com as categories como chaves e as qualities como valores.

julia> categories = ("item_name", "price", "color", "base_color");

julia> qualities = ("Descriptive Name", 99.00, "Ochre Red", "red");

julia> clothingitem(categories, qualities)
Dict{String, Any} with 4 entries:
  "price"      => 99.0
  "item_name"  => "Descriptive Name"
  "base_color" => "red"
  "color"      => "Ochre Red"

Sua função deve ser capaz de lidar com qualquer número de categories.

2. Sugira combinações

Implemente get_combinations() para receber um Tuple de peças de cima e um Tuple de peças de baixo. A função deve retornar o cartesian product dos tuples como um array 2-D (ou seja, uma Matrix). Cada entrada é uma combinação (top, bottom) como um Tuple. As peças de cima variam ao longo das linhas, as peças de baixo variam ao longo das colunas.

julia> tops = (
        Dict("item_name" => "Dress shirt"),
        Dict("item_name" => "Casual shirt")
        );

julia> bottoms = (
        Dict("item_name" => "Jeans"),
        Dict("item_name" => "Dress trousers")
       );

julia> get_combinations(tops, bottoms)
2×2 Matrix{Tuple{Dict{String, String}, Dict{String, String}}}:
 (Dict("item_name"=>"Dress shirt"), Dict("item_name"=>"Jeans"))   (Dict("item_name"=>"Dress shirt"), Dict("item_name"=>"Dress trousers"))
 (Dict("item_name"=>"Casual shirt"), Dict("item_name"=>"Jeans"))  (Dict("item_name"=>"Casual shirt"), Dict("item_name"=>"Dress trousers"))

3. Some os preços dos looks

Cada peça de roupa tem um campo price associado a ela, então pode ser útil conseguir comparar o preço total dos looks. Implemente get_prices(), que recebe um array de combinações de roupas. A função deve retornar um array com formato semelhante, com os preços dos looks em suas respectivas posições.

julia> tops = (
        Dict("item_name" => "Dress shirt", "base_color" => "blue", "price" => 35),
        Dict("item_name" => "Casual shirt", "base_color" => "black", "price" => 20)
       );

julia> bottoms = (
        Dict("item_name" => "Jeans", "base_color" => "blue", "price" => 30),
        Dict("item_name" => "Dress trousers", "base_color" => "black", "price" => 75)
       );

julia> combomatrix = get_combinations(tops, bottoms);

julia> get_prices(combomatrix)
2×2 Matrix{Int}::
 65  110
 50   95

julia> filteredmatrix = filter_clashing(combomatrix)
1-element Vector{Tuple{Dict{String, Any}, Dict{String, Any}}}:
 (Dict("price" => 20, "item_name" => "Casual shirt", "base_color" => "black"), Dict("price" => 30, "item_name" => "Jeans", "base_color" => "blue"))

julia> get_prices(filteredmatrix)
1-element Vector{Int}:
 50

4. Filtre os looks que não combinam

Cada peça de roupa tem um campo base_color. Use esse campo para remover todas as combinações em que a peça de cima e a peça de baixo têm a mesma cor base. Implemente filter_clashing() para receber um array de combinações de roupas. Retorne um array 1-D (ou seja, um Vector) das combinações resultantes.

julia> tops = (
        Dict("item_name" => "Dress shirt", "base_color" => "blue", "price" => 35),
        Dict("item_name" => "Casual shirt", "base_color" => "black", "price" => 20)
       );

julia> bottoms = (
        Dict("item_name" => "Jeans", "base_color" => "blue", "price" => 30),
        Dict("item_name" => "Dress trousers", "base_color" => "black", "price" => 75)
       );

julia> combos = get_combinations(tops, bottoms);

julia> filter_clashing(combos)
1-element Vector{Tuple{Dict{String, Any}, Dict{String, Any}}}:
 (Dict("price" => 20, "item_name" => "Casual shirt", "base_color" => "black"), Dict("price" => 30, "item_name" => "Jeans", "base_color" => "blue"))
Editar via GitHub O link abre em uma nova janela ou aba
Julia Exercism

Tudo pronto para começar Sugestões da boutique?

Crie sua conta no Exercism para aprender e dominar Julia com 35 conceitos128 exercícios e mentoria humana de verdade, tudo de graça.