0xDEADBEEF

[RSS]
««« »»»

Průnik množin ve Scale

3. 11. 2018

Dneska je čas na jeden malý trik jak ve Scale vy­po­čí­tat ve­li­kost prů­niku dvou množin. Když mám dvě mno­žiny asbs, dá se to za­ří­dit vy­tvo­ře­ním mno­žiny prů­niku.

as.intersect(bs).size

Jde o přímé řešení, které po­pi­suje, o přesně dělá, ale je je třeba alo­ko­vat do­čas­nou ko­lekci a to není nej­rych­lejší. Bez alo­kací se to samé dá za­ří­dit takhle:

var i = 0
for (a <- as if bs.conains(a)) i += 1

To je zase po­ně­kud zdlou­havé, ne­funk­ci­o­nální a také není na první pohled jasně vidět, co smyčka přesně dělá. Exis­tuje ale ještě jedno řešení, které vy­u­žívá bo­ha­tého API ko­lekcí Scaly, která je mnohem ele­gant­nější:

as.count(bs)

Metoda count spo­čítá kolik prvků z mno­žiny as od­po­vídá pre­di­kátu. Místo funkce je ale zadána druhá mno­žina. Fun­guje to proto, že mno­žina je ve Scale zá­ro­veň funkce tes­tu­jící člen­ství ele­mentu:

class Set[T] extends T => Boolean

Kom­pi­lá­tor pod ka­po­tou kód pře­píše na

as.count { a => bs.apply(a) }

což dělá to samé, co

as.count(bs.contains)

tedy počítá to počet prvků první mno­žiny, které jsou pří­tomny v té druhé, neboli ve­li­kost prů­niku.

Po­dobné kousky je možné pro­vá­dět i s mapami, které jsou ze své pod­staty (par­ci­ální) funkce z klíčů na ma­po­vané hod­noty:

class Map[K, V] extends K => V

Dá se tak napsat třeba jed­no­du­ché ge­ne­ro­vání slugů do url z ti­tulků článků:

val from = "áčďéěíňóřšťúůýž "
val to   = "acdeeinorstuuyz-"
val txl = (from zip to).toMap withDefault (x => x)
def makeSlug(title: String) = title.map(txl)

Pozn: Když chcete po­čí­tat prů­niky množin opravdu rychle, mám na tohle téma celý článek.

píše k47 (@kaja47, k47)