Kurzusok
/
Julia
Julia
/
Feladatok
/
Butikajánlások
Butikajánlások

Butikajánlások

Tanulófeladat

Bevezetés

Aki használt már Pythont, az szinte biztosan találkozott a listakomprehenziókkal, amelyek már a korai verziók óta a Python szintaxisának szerves részét képezik.

Egy ennyire kényelmes megoldás lassanként más nyelvekbe is utat tör magának, a Juliát is beleértve.

A Julia programozóinak a komprehenzió lehetőség, nem pedig kötelező eszköz, hiszen általában vannak alternatívák (broadcasting, magasabb rendű függvények stb.).

A komprehenzió azonban gyakran egyszerű, jól olvasható és hatékony módját kínálja egy tömb létrehozásának. Hogy végül használod-e, az végső soron személyes ízlés kérdése, akárcsak az, hogy miként vélekedsz a Pythonról a funkcionális nyelvekkel szemben.

A szintaxis nagyrészt a Pythonéból lett szinte változtatás nélkül átvéve, de kiegészült a többdimenziós tömbök kezelésével.

Egyváltozós

Nagyon pythonos, az opcionális if feltételt is beleértve.

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

A kimenet alakja a komprehenzió részleteitől függ: egyszerű esetekben jellemzően megegyezik a bemeneti kollekcióéval, egy if feltétel viszont Vectorrá lapítja.

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

Többváltozós, Vector kimenet

A Pythonhoz hasonlóan több for záradékunk is lehet különböző változókkal, akár ugyanazzal, akár eltérő bemeneti kollekcióval.

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

Ez az egymásba ágyazott ciklusokkal egyenértékű. A kimenet egydimenziós lesz, még mátrix bemenet esetén is.

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...)

Többváltozós, többdimenziós kimenet

Az előző szakaszban több for záradék szerepelt, amelyeket csupán szóközök választottak el egymástól.

Ebben a szakaszban egyetlen for van, a változókat pedig vessző választja el.

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)

A komprehenzió minden egyes változója egy-egy új dimenziót hoz létre a kimenetben, a változók minden lehetséges kombinációjához egy-egy bejegyzéssel.

A fenti példában x a sorok mentén növekszik lefelé, y pedig az oszlopok mentén jobbra. Nagyobb dimenziók is lehetségesek, a kimenet olvashatóságára vonatkozó szokásos fenntartásokkal.

Generátorkifejezések

Az előző szakaszok a tömbkimenetre összpontosítottak, ahol a komprehenzió szögletes zárójelek [ ... ] közé kerül.

Ha a szögletes zárójeleket kerek zárójelekre ( ... ) cseréljük, valami más történik: a kapott objektum egy generator expression, egy lustán kiértékelt iterátor, amely igény szerint adja a következő értéket.

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

Ha egy komprehenzió eredményét rögtön tovább dolgozzuk fel, a generátor memóriatakarékos lehet: így nem kell eltárolni egy nagy közbenső tömböt.

Ha egy generátort függvényargumentumként adunk át, nem kell külön zárójelbe tennünk.

# 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 generátor szintaxisa ugyanaz, mint a komprehenzióé, csak a körülvevő zárójelekben tér el.

A generátorok a szótárkonstruktorokban is kényelmesek lehetnek.

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

Utasítások

Egy online divatbutikban dolgozol. Beugrik egy ötleted egy weboldalfunkcióra, ahol a felhasználónak szetteket ajánlunk. A lehetséges szettek, azok árai és az össze nem illő lehetőségek kiszűrése mind érdekesek.

Note

Bár a következő feladatok megoldására többféle módszer is lehet, mindegyik megoldható egy comprehension használatával.

1. Hozz létre egy ruhadarabot

Valósítsd meg a clothingitem() függvényt, amely két Tuple-t kap: az egyik a categories, a másik a hozzájuk tartozó qualities. A függvény egy Dict-et adjon vissza, amelyben a kulcsok a categories, az értékek pedig a qualities.

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"

A függvényednek tetszőleges számú categories bejegyzést kezelnie kell.

2. Ajánlj kombinációkat

Valósítsd meg a get_combinations() függvényt, amely egy felsőkből álló Tuple-t és egy alsókból álló Tuple-t kap. A függvény a tuple-ök cartesian product-ját adja vissza kétdimenziós tömbként (azaz Matrix-ként). Minden elem egy (top, bottom) kombináció, Tuple-ként. A felsők a sorok mentén változnak, az alsók az oszlopok mentén.

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. Add össze a szettek árait

Minden ruhadarabhoz tartozik egy price mező, így hasznos lehet, ha össze tudjuk hasonlítani a szettek teljes árát. Valósítsd meg a get_prices() függvényt, amely ruhakombinációk tömbjét kapja. A függvény egy ugyanolyan alakú tömböt adjon vissza, amelyben a szettek árai a megfelelő helyükön szerepelnek.

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. Szűrd ki az össze nem illő szetteket

Minden ruhadarabnak van egy base_color mezője. Ezzel a mezővel távolítsd el az összes olyan kombinációt, ahol a felső és az alsó alapszíne megegyezik. Valósítsd meg a filter_clashing() függvényt, amely ruhakombinációk tömbjét kapja. Add vissza a megfelelő kombinációk egydimenziós tömbjét (azaz Vector-t).

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"))
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
Julia Exercism

Készen állsz elkezdeni a(z) Butikajánlások feladatot?

Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Julia nyelvet 35 fogalom128 feladat segítségével, valódi emberi mentorálással, mindez ingyen.