Pavel Fatin Scala Collections Tips and Tricksã®èšäºã®ç¿»èš³ã玹ä»ããŸãã Pavelã¯JetBrainsã§åããŠãããIntelliJ IDEAã®Scalaãã©ã°ã€ã³ãéçºããŠããŸã ã ããã«ãç©èªã¯èè
ã«ä»£ãã£ãŠããŸãã
ãã®èšäºã§ã¯ãScalaã³ã¬ã¯ã·ã§ã³APIã®æ¥åžžçãªäœ¿çšã«å
±éããåçŽåãšæé©åã«ã€ããŠèª¬æããŸã ã
äžéšã®ãã³ãã¯ãã³ã¬ã¯ã·ã§ã³ã©ã€ãã©ãªã®å®è£
ã®è€éãã«åºã¥ããŠããŸãããã»ãšãã©ã®ã¬ã·ãã¯ãå®éã«ã¯èŠèœãšãããã¡ãªã¹ããŒããªå€æã§ãã
ãã®ãªã¹ãã¯ã Scala IntelliJãã©ã°ã€ã³ã®ããã«ã Scala ã³ã¬ã¯ã·ã§ã³ã®å®çšçãªæ€æ»ãéçºããããšããç§ã®è©Šã¿ã«è§ŠçºãããŸããã çŸåšããããã®æ€æ»ãå®è£
ããŠããã®ã§ãIDEAã§Scalaãã©ã°ã€ã³ã䜿çšãããšãéçã³ãŒãåæããèªåçã«æ©æµãåããŸãã
ãã ãããããã®ã¬ã·ãã¯ããèªäœã§äŸ¡å€ããããŸãã ãããã¯ãScalaæšæºã³ã¬ã¯ã·ã§ã³ã©ã€ãã©ãªã®çè§£ãæ·±ããã³ãŒããããé«éã§è¡šçŸåè±ãã«ããã®ã«åœ¹ç«ã¡ãŸãã
æŽæ°ïŒ
åéºå¿ããããªãã
é©åãªã€ã³ã¹ãã¯ã·ã§ã³ãéžæããããšã§ã Scalaçšã®IntelliJãã©ã°ã€ã³ã®éçºãæ¯æŽããå®è£
ãè©Šãæ¹æ³ãåŠã¶ããšãã§ããŸãã
å
容ïŒ
1. 2. 3. 4. (Sequences) 4.1. 4.2. 4.3. 4.4. 4.5. 4.6. 4.7. 4.8. 4.9. 4.10. 5. (Sets) 6. Option- 6.1. 6.2. Null 6.3. 6.4. 7. 8.
ãã¹ãŠã®ãµã³ãã«ã³ãŒãã¯GitHubã®ãªããžããªããå
¥æã§ããŸã ã
1.å¡äŸ
ã³ãŒãäŸãããããããããããã«ã次ã®è¡šèšã䜿çšããŸããã
seqã¯ã Seq(1, 2, 3)ãããªSeq(1, 2, 3)ããŒã¹ã®ã³ã¬ã¯ã·ã§ã³ã®ã€ã³ã¹ã¿ã³ã¹ã§ãset - Setã€ã³ã¹ã¿ã³ã¹ãããšãã°Set(1, 2, 3)array - Array(1, 2, 3)ãªã©ã®Array(1, 2, 3)option - Optionã€ã³ã¹ã¿ã³ã¹ãããšãã°Some(1)map - Mapé¡äŒŒããMapã€ã³ã¹ã¿ã³ã¹Map(1 -> "foo", 2 -> "bar")??? -ä»»æã®è¡šçŸp - T => Booleanåã®é¢æ°ã®è¿°éšãããšãã°_ > 2nã¯æŽæ°å€ã§ãiã¯æŽæ°ã€ã³ããã¯ã¹ã§ãf ã gã¯åçŽãªé¢æ°ã A => Bx ã yããã€ãã®ä»»æã®å€zåæå€ãŸãã¯ããã©ã«ãå€Pãã¿ãŒã³
2.æ§æ
ã¬ã·ãã¯å€ç«ããŠããŠèªçµŠèªè¶³ã§ãããšããäºå®ã«ãããããããæ¬¡ã®ããé«åºŠãªè¡šçŸãžã®æŒžé²çãªå€æã®ããã«èª¿æŽã§ããããšãå¿ããªãã§ãã ããã
seq.filter(_ == x).headOption != None // seq.filter(p).headOption seq.find(p) seq.find(_ == x) != None // option != None option.isDefined seq.find(_ == x).isDefined // seq.find(p).isDefined seq.exists(p) seq.exists(_ == x) // seq.exists(_ == x) seq.contains(x) seq.contains(x)
ãã®ãããã亀æåŠæ¹ã¢ããªã±ãŒã·ã§ã³ã¢ãã«ãïŒ SICPã«é¡äŒŒïŒã«äŸåããããã䜿çšããŠè€éãªè¡šçŸãç°¡çŽ åã§ããŸãã
3.å¯äœçš
ããµã€ã广ãã¯ãäž»èŠãªå€æããªã¹ãããåã«èæ
®ãã¹ãåºæ¬çãªæŠå¿µã§ãã
å®éãå¯äœçšãšã¯ãå€ãè¿ãããšã«å ããŠã颿°ãŸãã¯åŒã®å€åŽã§èгå¯ãããã¢ã¯ã·ã§ã³ã®ããšã§ããäŸãã°ïŒ
- å
¥åºåæäœ
- 倿°ã®å€æŽïŒã¹ã³ãŒãå€ã§å©çšå¯èœïŒ
- ãªããžã§ã¯ãã®ç¶æ
ã®å€åïŒã¹ã³ãŒãå€ã§èгå¯ïŒ
- äŸå€ãã¹ããŒããŸãïŒã¹ã³ãŒãå
ã§ãåŠçãããŸããïŒã
äžèšã®ã¢ã¯ã·ã§ã³ã®ãããããå«ã颿°ãŸãã¯åŒã¯å¯äœçšããããšèšãããããã§ãªããã°ãçŽç²ããšåŒã°ããŸãã
ãªãå¯äœçšãããã»ã©éèŠãªã®ã§ããïŒ åœŒããšå®è¡ã®é åºãéèŠã ããã§ãã ããšãã°ã2ã€ã®ãçŽç²ãªãåŒïŒå¯Ÿå¿ããå€ã«é¢é£ä»ããããŠããŸãïŒïŒ
val x = 1 + 2 val y = 2 + 3
ãããã«ã¯å¯äœçšïŒããªãã¡ãåŒã®å€åŽã§èгå¯ããã广ïŒãå«ãŸããŠããªãããããããã®åŒãä»»æã®é åºã§èšç®ã§ããŸã-æåã«x ãæ¬¡ã«yãŸãã¯æåã«y ãæ¬¡ã«xããã¯åŸãããçµæã®æ£ç¢ºãã«åœ±é¿ããŸããïŒå¿
èŠã«å¿ããŠãçµæã®å€ããã£ãã·ã¥ããããšãã§ããŸãïŒã 次ã«ã次ã®å€æŽãæ€èšããŸãã
val x = { print("foo"); 1 + 2 } val y = { print("bar"); 2 + 3 }
ããã¯å¥ã®è©±ã§ã-ã¿ãŒããã«ã§ã¯ãfoobarãã®ä»£ããã«ãbarfooããåºåãããããå®è¡é åºã倿Žããããšã¯ã§ããŸããïŒããã¯æããã«æå³ãããã®ã§ã¯ãããŸããïŒã
ãã®ãããå¯äœçšã®ååšã¯ãã³ãŒãã«é©çšã§ãã倿 ïŒåçŽåãšæé©åã®äž¡æ¹ïŒ ã®æ°ãæžãããŸãã
åæ§ã®èæ
®äºé
ã¯ãé¢é£ããã³ã¬ã¯ã·ã§ã³ãåŒã«ãé©çšãããŸãã ç¯å²å€ã®ã©ããã«ç¹å®ã®builderããããšæ³åããŠãã ããïŒ
seq.filter(x => { builder.append(x); x > 3 }).headOption
ååãšããŠã seq.filter(p).headOptionåŒã³åºãã¯seq.filter(p).headOptionç°¡ç¥åãããŠããŸãããå¯äœçšseq.find(p)ããããããè¡ãseq.find(p)ãã
seq.find( x => {builder.append(x); x > 3 })
ãããã®åŒã¯æçµå€ã®ç¹ã§ã¯åçã§ãããå¯äœçšã®ç¹ã§ã¯åçã§ã¯ãããŸããã æåã®åŒã¯ãã¹ãŠã®èŠçŽ ã远å ããæåŸã®åŒã¯è¿°èªã«äžèŽããæåã®å€ãèŠã€ãããšããã«ãã¹ãŠã®èŠçŽ ãç Žæ£ããŸãã ãããã£ãŠããã®ãããªåçŽåã¯ã§ããŸããã
èªåç°¡çŽ åãå¯èœã«ããããã«äœãã§ããŸããïŒ çãã¯ãã³ãŒãå
ã®ãã¹ãŠã®å¯äœçšïŒååãšããŠã³ã¬ã¯ã·ã§ã³ããªããã®ãå«ãïŒã«é¢ããŠåŸãã¹ãé»éåŸã§ãïŒ
- å¯èœãªéãå¯äœçšãé¿ããŠãã ããã
- ãã以å€ã®å Žåãå¯äœçšãã¯ãªãŒã³ãªã³ãŒãããåé¢ããŸãã
ãããã£ãŠã builder aãïŒå¯äœçšãããAPIãšãšãã«ïŒåãé€ããã builder aã®åŒã³åºããçŽç²ãªåŒããåé¢ããå¿
èŠããããŸãã ãã®builderã¯ãåé€ã§ããªããµãŒãããŒãã£ã®ãªããžã§ã¯ãã§ãããšæ³å®ããŸãããã®ãããåŒã³åºãã®ã¿ãåé¢ã§ããŸãã
seq.foreach(builder.append) seq.filter(_ > 3).headOption
ããã§ãå®å
šã«å€æãå®è¡ã§ããŸãã
seq.foreach(builder.append) seq.find(x > 3)
æž
æœã§çŸããïŒ å¯äœçšã®åé¢ã«ãããèªå倿ãå¯èœã«ãªããŸããã 远å ã®å©ç¹ã¯ãæç¢ºãªåé¢ãååšãããããçµæã®ã³ãŒãã人ãçè§£ãããããªãããšã§ãã
å¯äœçšãåé¢ããããšã®æãæçœã§ãåæã«æãéèŠãªå©ç¹ã¯ãä»ã®å¯èœãªæé©åã«é¢ä¿ãªããã³ãŒãã®ä¿¡é Œæ§ãåäžãããããšã§ãã äŸã«ã€ããŠïŒåæåŒã¯ã SeqçŸåšã®å®è£
ã«å¿ããŠãããŸããŸãªå¯äœçšãåŒãèµ·ããå¯èœæ§ããããŸãã ããšãã°ã Vectorå Žåããã¹ãŠã®èŠçŽ ã远å ããã Streamå Žåãè¿°èªãšã®æåã®äžèŽãæåããåŸããã¹ãŠã®èŠçŽ ãã¹ããããããŸãïŒã¹ããªãŒã ã¯ãé
å»¶ãã§ãããããèŠçŽ ã¯å¿
èŠãªå Žåã«ã®ã¿èšç®ãããŸãïŒã å¯äœçšã®åé¢ã«ããããããã®äžç¢ºå®æ§ãåé¿ã§ããŸãã
4.ã·ãŒã±ã³ã¹
ãã®ã»ã¯ã·ã§ã³ã®ã¢ããã€ã¹ã¯Seqçžç¶äººã«é©çšãããŸãããäžéšã®å€æã¯ä»ã®ã¿ã€ãã®ã³ã¬ã¯ã·ã§ã³ïŒã³ã¬ã¯ã·ã§ã³ã§ã¯ãªãïŒã«æå¹ã§ããããšãã°ã Set ã Option ã Mapããã«ã¯Iterator ïŒãããã¯ãã¹ãŠã¢ããã¡ãœãããšåæ§ã®ã€ã³ã¿ãŒãã§ãŒã¹ãæäŸããããïŒ
4.1äœæ
空ã®ã³ã¬ã¯ã·ã§ã³ãæç€ºçã«äœæãã
// Seq[T]() // Seq.empty[T]
äžéšã®äžå€ã®ã³ã¬ã¯ã·ã§ã³ã¯ã©ã¹ã«ã¯ã emptyã¡ãœããã®ã·ã³ã°ã«ãã³å®è£
ãããempty ã ãã ãããã¹ãŠã®ãã¡ã¯ããªã¡ãœãããäœæãããã³ã¬ã¯ã·ã§ã³ã®é·ãããã§ãã¯ããããã§ã¯ãããŸããã ãã®ãããã³ã³ãã€ã«æ®µéã§voidãæå®ããããšã«ãããããŒãäžã®ã¹ããŒã¹ïŒã€ã³ã¹ã¿ã³ã¹ã®åå©çšã«ããïŒãŸãã¯ããã»ããµãŒãµã€ã¯ã«ïŒå®è¡æã®æ¬¡å
ãã§ãã¯ã«è²»ããããšãã§ããïŒãç¯çŽã§ããŸãã
以äžã«ãé©çšå¯èœïŒ Set ã Option ã Map ã Iterator ã
4.2é·ã
é
åã®å Žåã size代ããã«lengthã䜿çšãsize
// array.size // array.length
sizeãšlengthã¯æ¬è³ªçã«å矩ã§ãããScala 2.11ã§ã¯Array.sizeåŒã³åºãã¯æé»ã®å€æã«ãã£ãŠè¡ãããåã¡ãœããåŒã³åºãã®äžéã©ãããŒãªããžã§ã¯ããäœæããŸãã ãã¡ãããJVMã®ãšã¹ã±ãŒãåæãæå¹ã«ããªãéããäžæãªããžã§ã¯ãã¯ã¬ããŒãžã³ã¬ã¯ã¿ãŒã®è² æ
ã«ãªããã³ãŒãã®ããã©ãŒãã³ã¹ãäœäžãããŸãïŒç¹ã«ã«ãŒãå
ïŒã
isEmptyãæåŠããªãã§ãã ãã
// !seq.isEmpty !seq.nonEmpty // seq.nonEmpty seq.isEmpty
åçŽãªããããã£ã¯ãè€ååŒãããèŠèŠçãªãã€ãºãå°ãªãã§ãã
以äžã«ãé©çšå¯èœïŒ Set ã Option ã Map ã Iterator ã
voidããã§ãã¯ãããšãã«é·ããèšç®ããªãã§ãã ããã
äžæ¹ã§ã¯ãåçŽãªããããã£ã¯è€ååŒãããã¯ããã«ç°¡åã«èªèãããŸãã äžæ¹ã LinearSeqçžç¶äººïŒ Listãªã©ïŒã¯ããªã¹ãã®é·ããèšç®ããããã«ïŒ IndexedSeq O(1)代ããã«O(n)æéãå¿
èŠãšããå Žåããããããäžè¬çã«ãé·ãã®èšç®ãé¿ããããšã§ã³ãŒããé«éåã§ããŸãããã®å€ã¯ããŸãå¿
èŠãããŸããã
ç¡éã¹ããªãŒã ã®.lengthåŒã³åºãã¯æ±ºããŠçµäºããªãå¯èœæ§ããããããåžžã«æç€ºçã«ã¹ããªãŒã ã®ç©ºæ§ã確èªããŠãã ããã
é©çšå¯Ÿè±¡ïŒ Set ã Map ã
æ¯èŒäžã«ã³ã¬ã¯ã·ã§ã³ã®ãã«ãµã€ãºãèšç®ããªãã§ãã ããã
// seq.length > n seq.length < n seq.length == n seq.length != n // seq.lengthCompare(n) > 0 seq.lengthCompare(n) < 0 seq.lengthCompare(n) == 0 seq.lengthCompare(n) != 0
ã³ã¬ã¯ã·ã§ã³ã®ãµã€ãºã®èšç®ã¯ãäžéšã®ã¿ã€ãã®ã³ã¬ã¯ã·ã§ã³ã§ã¯éåžžã«ãé«äŸ¡ãªãèšç®ã«ãªãå¯èœæ§ãããããã LinearSeq ïŒ Seqå€ã§é衚瀺ã«ã§ããO(length min n)ã®æ¯èŒæéãO(length)ããO(length min n)ã«LinearSeqã§ããŸãã ããã«ãç¡éã®ã¹ããªãŒã ãåŠçããå Žåããã®ã¢ãããŒãã¯äžå¯æ¬ ã§ãã
emptyããã§ãã¯ããããã«existsã䜿çšããªãã§ãã ããã
// seq.exists(_ => true) seq.exists(const(true)) // seq.nonEmpty
ãã¡ããããã®ãããªããªãã¯ã¯å®å
šã«åé·ã§ãã
é©çšå¯Ÿè±¡ïŒã»ããããªãã·ã§ã³ãããããã€ãã¬ãŒã¿ãŒã
4.3å¹³ç
é
åã®å
å®¹ãæ¯èŒããããã«==ã«äŸåããªãã§ãã ãã
ç䟡æ§ãã¹ãã¯ãé
åã®ããŸããŸãªã€ã³ã¹ã¿ã³ã¹ã«å¯ŸããŠåžžã«falseãè¿ããŸãã
該åœãããã®ïŒ Iterator
ç°ãªãã«ããŽãªã®ã³ã¬ã¯ã·ã§ã³ã®åçæ§ããã¹ãããªãã§ãã ãã
// seq == set // seq.toSet == set
ç䟡æ§ãã§ãã¯ã䜿çšããŠãã³ã¬ã¯ã·ã§ã³ãšç°ãªãã«ããŽãªïŒäŸïŒ ListãšSet ïŒãæ¯èŒã§ããŸãã
ãã®ãã§ãã¯ã®æå³ã«ã€ããŠåèããŠãã ããïŒäžèšã®äŸ-ã·ãŒã±ã³ã¹å
ã®éè€ãã©ã®ããã«èæ
®ãããïŒã
sameElementsã䜿çšããŠéåžžã®ã³ã¬ã¯ã·ã§ã³ãæ¯èŒããªãã§ãã ãã
åçæ§ãã¹ãã¯ãåãã«ããŽãªã®ã³ã¬ã¯ã·ã§ã³ãæ¯èŒããæ¹æ³ã§ãã çè«çã«ã¯ãããã«ãããæœåšçãªã€ã³ã¹ã¿ã³ã¹ãã§ãã¯ãåå ã§ããã©ãŒãã³ã¹ãåäžããããšããããŸãïŒ eq ãéåžžã¯ã¯ããã«é«éïŒã
æç€ºçã«å¯Ÿå¿ã䜿çšããªãã§ãã ãã
åãããšãè¡ãçµã¿èŸŒã¿ã¡ãœãããæ¢ã«ãããŸãã äž¡æ¹ã®åŒã§ã¯ãèŠçŽ ã®é åºãèæ
®ãããŸãã ç¹°ãè¿ãã«ãªããŸãããçç£æ§ã®åäžã®æ©æµãåããããšãã§ããŸãã
4.4玢åŒä»ã
ã€ã³ããã¯ã¹ã§æåã®ã¢ã€ãã ãååŸããªãã§ãã ãã
// seq(0) // seq.head
äžéšã®ã³ã¬ã¯ã·ã§ã³ã¯ã©ã¹ã§ã¯ãæŽæ°ãããã¢ãããŒããå°ãéããªãå ŽåããããŸãïŒããšãã°ã List.applyã³ãŒãã確èªããŠãã ããïŒã ããã«ãããããã£ãžã®ã¢ã¯ã»ã¹ã¯ãåŒæ°ã䜿çšããŠã¡ãœãããåŒã³åºããããã¯ããã«ç°¡åã§ãïŒæ§æçã«ãæå³çã«ãïŒã
ã€ã³ããã¯ã¹ã§æåŸã®ã¢ã€ãã ãååŸããªãã§ãã ãã
// seq(seq.length - 1) // seq.last
æåŸã®åŒã¯ããæç¢ºã§ãã³ã¬ã¯ã·ã§ã³ã®é·ãã®äžå¿
èŠãªèšç®ãé¿ããŸãïŒãããŠç·åœ¢ã·ãŒã±ã³ã¹ã®å Žåãããã«ã¯å€ãã®æéãããããŸãïŒã ããã«ãäžéšã®ã³ã¬ã¯ã·ã§ã³ã¯ã©ã¹ã¯ãã€ã³ããã¯ã¹ã¢ã¯ã»ã¹ãããå¹ççã«æåŸã®ã¢ã€ãã ãååŸã§ããŸãã
ã³ã¬ã¯ã·ã§ã³å
ã®ã€ã³ããã¯ã¹ãæç€ºçã«ãã§ãã¯ããªãã§ãã ãã
// if (i < seq.length) Some(seq(i)) else None // seq.lift(i)
æå³çã«ã¯ã2çªç®ã®åŒã¯åçã§ããããã衚çŸçã«ã¯
headOptionããšãã¥ã¬ãŒãããªãã§ãã ãã
// if (seq.nonEmpty) Some(seq.head) else None seq.lift(0) // seq.headOption
ç°¡ç¥åãããåŒã¯ããç°¡æœã§ãã
lastOptionãšãã¥ã¬ãŒãããªã
// if (seq.nonEmpty) Some(seq.last) else None seq.lift(seq.length - 1) // seq.lastOption
æåŸã®åŒã¯çããªã£ãŠããŸãïŒãããŠæœåšçã«é«éã§ãïŒã
indexOfããã³lastIndexOfåŒæ°ã¿ã€ãã«æ³šæããŠãã ãã
// Seq(1, 2, 3).indexOf("1") // Seq(1, 2, 3).lastIndexOf("2") // // Seq(1, 2, 3).indexOf(1) Seq(1, 2, 3).lastIndexOf(2)
忣ã®indexOfã«ããã indexOfã¡ãœãããšlastIndexOfã¡ãœããã¯Anyåã®åŒæ°ãåãå
¥ããŸãã å®éã«ã¯ãããã«ãããã³ã³ãã€ã«æ®µéã§æ€åºã§ããªããã°ãèŠã€ãã«ãããªããŸãã IDEã®ãµããŒãæ€æ»ãè¡ãããå Žæã§ãã
ã·ãŒã±ã³ã¹ã€ã³ããã¯ã¹ã®ç¯å²ãæåã§äœæããªãã§ãã ãã
ã·ãŒã±ã³ã¹å
ã®ãã¹ãŠã®ã€ã³ããã¯ã¹ã®ç¯å²ãè¿ãçµã¿èŸŒã¿ã¡ãœããããããŸãã
ã³ã¬ã¯ã·ã§ã³ãã€ã³ããã¯ã¹ã«æåã§é¢é£ä»ããããã«zipã䜿çšããªãã§ãã ãã
ãŸããæåŸã®åŒãçããªããŸãã ããã«ãã³ã¬ã¯ã·ã§ã³ã®ãµã€ãºã®é ãããèšç®ïŒç·åœ¢ã·ãŒã±ã³ã¹ã®å Žåã¯é«äŸ¡ã«ãªãå¯èœæ§ãããïŒãé¿ããããšã«ãããããã©ãŒãã³ã¹ã®åäžãæåŸ
ã§ããŸãã
åŸè
ã®åŒã®è¿œå ã®å©ç¹ã¯ãç¡éã®ã³ã¬ã¯ã·ã§ã³ïŒäŸïŒ Stream ïŒã§ããŸãæ©èœããããšã§ãã
IndexedSeqã€ã³ã¹ã¿ã³ã¹ã颿°ãªããžã§ã¯ããšããŠäœ¿çšããŸãã
// (seq: IndexedSeq[T]) Seq(1, 2, 3).map(seq(_)) // Seq(1, 2, 3).map(seq)
IndexedSeq[T]ã€ã³ã¹ã¿ã³ã¹ã¯Function1[Int, T]ã§ãããããããã®ãŸãŸäœ¿çšã§ããŸãã
4.5ååš
æ¯èŒè¿°èªã䜿çšããŠèŠçŽ ããã§ãã¯ããªãã§ãã ãã
2çªç®ã®åŒã¯æå³çã«åçã§ããããã衚çŸåè±ãã§ãã ãããã®åŒãSetã«é©çšããããšãã»ããæ€çŽ¢ã¯O(1)ãªãåŸåããããããããã©ãŒãã³ã¹ãåçã«ç°ãªãå¯èœæ§ããããŸãO(1) existså Žåexistså
éšã€ã³ããã¯ã¹ã䜿çšãããªãããïŒã
以äžã«ãé©çšå¯èœïŒ Set ã Option ã Iterator ã
containsããåŒæ°ã®ã¿ã€ãã«æ³šæããŠãã ãã
// Seq(1, 2, 3).contains("1") // // Seq(1, 2, 3).contains(1)
indexOfãlastIndexOfããã«ãã¿ã€ãAnyåŒæ°ãåãã¡ãœãããcontainsãŸããããã«ãããã³ã³ãã€ã«æ®µéã§ã¯æ€åºãããªããã°ãèŠã€ãã«ãããªããŸãã ãããã«æ³šæããŠãã ããã
äžçåŒè¿°éšã䜿çšããŠãæ¬ èœããŠããèŠçŽ ããã§ãã¯ããªãã§ãã ãã
// seq.forall(_ != x) // !seq.contains(x)
ç¹°ãè¿ããŸãããæåŸã®åŒã¯ããã¯ãªãŒã³ã§ãããããããé«éã§ãïŒç¹ã«ã»ããã®å ŽåïŒã
以äžã«ãé©çšå¯èœïŒ Set ã Option ã Iterator ã
çºçãã«ãŠã³ãããŠååšã確èªããªã
// seq.count(p) > 0 seq.count(p) != 0 seq.count(p) == 0 // seq.exists(p) seq.exists(p) !seq.exists(p)
æããã«ãæ¡ä»¶ã«äžèŽããã¢ã€ãã ãã³ã¬ã¯ã·ã§ã³å
ã«ãããã©ãããç¥ãå¿
èŠãããå ŽåãäžèŽããã¢ã€ãã ã®æ°ãã«ãŠã³ãããããšã¯åé·ã§ãã ç°¡ç¥åãããåŒã¯ãããã¯ãªãŒã³ã§é«éã«èŠããŸãã
- è¿°èª
pã¯çŽé¢æ°ã§ãªããã°ãªããŸããã - 該åœãããã®ïŒ
Set ã Map ã Iterator ã
ååšã確èªããããã«ãã£ã«ã¿ãªã³ã°ã«é Œããªãã§ãã ãã
// seq.filter(p).nonEmpty seq.filter(p).isEmpty // seq.exists(p) !seq.exists(p)
filteråŒã³åºãã¯ãããŒãã®ã¹ããŒã¹ãå æããŠGCãããŒãããäžéã³ã¬ã¯ã·ã§ã³ãäœæããŸãã ããã«ãåè¿°ã®åŒã¯ãã¹ãŠã®ãªã«ã¬ã³ã¹ãæ€åºããŸãããæåã®åŒã®ã¿ãæ€åºããå¿
èŠããããŸãïŒã³ã¬ã¯ã·ã§ã³ã®å¯èœãªå
容ã«ãã£ãŠã¯ã³ãŒããé
ããªãå¯èœæ§ããããŸãïŒã é
å»¶ã³ã¬ã¯ã·ã§ã³ïŒ Streamããç¹ã«Iterator ïŒã®å Žåãæœåšçãªããã©ãŒãã³ã¹ã®åäžã¯ããã»ã©éèŠã§ã¯ãããŸããã
- è¿°èª
pã¯çŽé¢æ°ã§ãªããã°ãªããŸããã - 以äžã«ãé©çšå¯èœïŒ
Set ã Option ã Map ã Iterator ã
ååšã確èªããããã«æ€çŽ¢ã«é Œããªãã§ãã ãã
// seq.find(p).isDefined seq.find(p).isEmpty // seq.exists(p) !seq.exists(p)
æ€çŽ¢ã¯ãã£ã«ã¿ãªã³ã°ãããééããªãåªããŠããŸãããããã¯å¶éããã¯ã»ã©é ãã§ãïŒå°ãªããšãæç¢ºãã®ç¹ã§ã¯ïŒã
以äžã«ãé©çšå¯èœïŒ Set ã Option ã Map ã Iterator ã
4.6ãã£ã«ã¿ãªã³ã°
ãã£ã«ã¿ãŒè¿°èªãæåŠããªãã§ãã ãã
æåŸã®åŒã¯æ§æçã«åçŽã§ãïŒæå³çã«åçã§ãããšããäºå®ã«ããããããïŒã
以äžã«ãé©çšå¯èœïŒ Set ã Option ã Map ã Iterator ã
ã«ãŠã³ãããããã«ãã£ã«ã¿ãªã³ã°ããªãã§ãã ãã
// seq.filter(p).length // seq.count(p)
filteråŒã³åºãã¯ãäžéã®ïŒããŸãå¿
èŠã§ã¯ãªãïŒã³ã¬ã¯ã·ã§ã³ãäœæããŸããããã¯ãããŒãã®ã¹ããŒã¹ãå æããGCãããŒãããŸãã
以äžã«ãé©çšå¯èœïŒ Set ã Option ã Map ã Iterator ã
æåã®åºçŸãèŠã€ããããã«ãã£ã«ã¿ãªã³ã°ã䜿çšããªãã§ãã ãã
ãã¡ããã seqé
å»¶ã³ã¬ã¯ã·ã§ã³ïŒ Streamãªã©ïŒã§ãªãå Žåãæåã®èŠçŽ ã®ã¿ãå¿
èŠã§ãããšããäºå®ã«ããããããããã£ã«ã¿ãªã³ã°ã¯ãã¹ãŠã®çºçãæ€åºïŒããã³äžæã³ã¬ã¯ã·ã§ã³ãäœæïŒããŸãã
以äžã«ãé©çšå¯èœïŒ Set ã Option ã Map ã Iterator ã
4.7äžŠã¹æ¿ã
ããããã£ã§æåã§äžŠã¹æ¿ããªãã§ãã ãã
// seq.sortWith(_.property < _.property) // seq.sortBy(_.property)
ãããè¡ãã«ã¯ãããæç¢ºã§è¡šçŸåè±ããªç¬èªã®æ¹æ³ããããŸãã
IDã§æåã§äžŠã¹æ¿ããªãã§ãã ãã
ãããŠããã®ããã®æ¹æ³ããããŸãã
ã¯ã³ã¹ãããã§éãœãŒã
// seq.sorted.reverse seq.sortBy(_.property).reverse seq.sortWith(f(_, _)).reverse // seq.sorted(Ordering[T].reverse) seq.sortBy(_.property)(Ordering[T].reverse) seq.sortWith(!f(_, _))
ãããã£ãŠãäžéã³ã¬ã¯ã·ã§ã³ã®äœæãåé¿ãã远å ã®å€æãæé€ã§ããŸãïŒããŒãã¹ããŒã¹ãšããã»ããµãµã€ã¯ã«ãç¯çŽããããïŒã
ãœãŒãã䜿çšããŠæå°èŠçŽ ãèŠã€ããªãã§ãã ãã
// seq.sorted.head seq.sortBy(_.property).head // seq.min seq.minBy(_.property)
åŸè
ã®ã¢ãããŒãã¯ãã衚çŸåè±ãã§ãã ããã«ã远å ã®ã³ã¬ã¯ã·ã§ã³ãäœæãããªããšããäºå®ã«ãããããé«éã«åäœããŸãã
æå€§ã®èŠçŽ ãèŠã€ããããã«ãœãŒãã䜿çšããªãã§ãã ãã
// seq.sorted.last seq.sortBy(_.property).last // seq.max seq.maxBy(_.property)
説æã¯åã®ãã³ããšåãã§ãã
4.8ç³ã¿èŸŒã¿
éé¡ãæåã§èšç®ããªãã§ãã ãã
ãã®ã¢ãããŒãã®å©ç¹ã¯ãæå¿«ããšè¡šçŸåã§ãã
- ãã®ä»ã®å¯èœãªæ¹æ³ïŒ
reduceLeft ã reduceRight ã foldLeft ã foldRight ã zã0çããå Žåã2çªç®ã®å€æã¯æåã®å€æã«çœ®ãæããããšãã§ããŸãã- 該åœãããã®ïŒ
Set ã Iterator ã
äœæ¥ãæåã§èšç®ããªãã§ãã ãã
çç±ã¯ãåã®ã±ãŒã¹ãšåãã§ãã
zã1å Žåã2çªç®ã®å€æã¯æåã®å€æã«çœ®ãæããããšãã§ããŸãã- 該åœãããã®ïŒ
Set ã Iterator ã
æå°ã¢ã€ãã ãæåã§æ€çŽ¢ããªãã§ãã ãã
// seq.reduce(_ min _) seq.fold(z)(_ min _) // seq.min z min seq.min
çè«çæ ¹æ ã¯åã®ã±ãŒã¹ãšåãã§ãã
該åœãããã®ïŒ Set ã Iterator ã
æå€§ã¢ã€ãã ãæåã§æ€çŽ¢ããªãã§ãã ãã
// seq.reduce(_ max _) seq.fold(z)(_ max _) // seq.max z max seq.max
ãã¹ãŠåã®ã±ãŒã¹ãšåãã§ãã
該åœãããã®ïŒ Set ã Iterator ã
forallãšãã¥ã¬ãŒãããªã
// seq.foldLeft(true)((x, y) => x && p(y)) !seq.map(p).contains(false) // seq.forall(p)
ç°¡çŽ åã®ç®æšã¯ãæå¿«ããšè¡šçŸåã§ãã
- è¿°èª
pã¯çŽé¢æ°ã§ãªããã°ãªããŸããã - 以äžã«ãé©çšå¯èœïŒ
Set ã Option ïŒ2è¡ç®ïŒã Iterator ã
ãšãã¥ã¬ãŒãããªã
// seq.foldLeft(false)((x, y) => x || p(y)) seq.map(p).contains(true) // seq.exists(p)
ãã¹ãŠã®æå¿«ããšè¡šçŸåã§ãæåŸã®åŒã¯ããé«éã«åäœãïŒæåã®é©åãªèŠçŽ ãèŠã€ãããšããã«åŸç¶ã®èŠçŽ ã®åŠçã忢ããŸãïŒãç¡éã®ã·ãŒã±ã³ã¹ã§æ©èœããŸãã
- è¿°èª
pã¯çŽé¢æ°ã§ãªããã°ãªããŸããã - 以äžã«ãé©çšå¯èœïŒ
Set ã Option ïŒ2è¡ç®ïŒã Iterator ã
mapãšãã¥ã¬ãŒãããŸãã
// seq.foldLeft(Seq.empty)((acc, x) => acc :+ f(x)) seq.foldRight(Seq.empty)((x, acc) => f(x) +: acc) // seq.map(f)
ããã¯ãç³ã¿èŸŒã¿ã«ãããããïŒãããïŒã®é¢æ°åããã°ã©ãã³ã°å®è£
ã®ãã¯ã©ã·ãã¯ãã§ãã ééããªãæçã§ãããã䜿çšããå¿
èŠã¯ãªãã ãããè¡ãã«ã¯ãçµã¿èŸŒã¿ã®è¡šçŸåè±ããªã¡ãœããã䜿çšããŸãïŒããã¯ãå®è£
ã§åçŽãªwhile䜿çšãããããé«éã§ãïŒã
以äžã«ãé©çšå¯èœïŒ Set ã Option ã Iterator ã
filterãšãã¥ã¬ãŒãããªã
// seq.foldLeft(Seq.empty)((acc, x) => if (p(x)) acc :+ x else acc) seq.foldRight(Seq.empty)((x, acc) => if (p(x)) x +: acc else acc) // seq.filter(p)
çç±ã¯ãåã®ã±ãŒã¹ãšåãã§ãã
以äžã«ãé©çšå¯èœïŒ Set ã Option ã Iterator ã
reverseãšãã¥ã¬ãŒãããªã
// seq.foldLeft(Seq.empty)((acc, x) => x +: acc) seq.foldRight(Seq.empty)((x, acc) => acc :+ x) // seq.reverse
ç¹°ãè¿ãã«ãªããŸãããçµã¿èŸŒã¿ã®ã¡ãœããã¯ããé«éã§ã¯ãªãŒã³ã§ãã
以äžã«ãé©çšå¯èœïŒ Set ã Option ã Iterator ã
4.9æ¯èŒ
Scalaã§ã®ãã¿ãŒã³ãããã³ã°ãšéšå颿°ã®ã¹ã¿ã³ãã¢ãã³ã®ãã³ããæ¬¡ã«ç€ºããŸã ã
ãã¿ãŒã³ãããã³ã°ãæã€é¢æ°ã®ä»£ããã«éšå颿°ã䜿çšãã
// seq.map { _ match { case P => ??? // x N } } // seq.map { case P => ??? // x N }
æŽæ°ãããåŒã¯åæ§ã®çµæãäžããããã·ã³ãã«ã«èŠããŸãã
äžèšã®å€æã¯ã map颿°ã®åŒæ°ã ãã§ãªããä»»æã®é¢æ°ã«é©çšã§ããŸãã ãã®ãã³ãã¯ã³ã¬ã¯ã·ã§ã³ã«éå®ãããŸããã ãã ããScalaã³ã¬ã¯ã·ã§ã³ã©ã€ãã©ãªAPIã®é«é颿°ã®æ®éæ§ãèæ
®ãããšããã®é¢æ°ã¯äŸ¿å©ã§ãã
flatMap collect
// seq.flatMap { case P => Seq(???) // x N case _ => Seq.empty } // seq.collect { case P => ??? // x N }
.
: Set , Option , Map , Iterator .
match collect ,
// v match { case P => Seq(???) // x N case _ => Seq.empty } // Seq(v) collect { case P => ??? // x N }
, case- , , match collect . , case .
Option , .
: Set , Option , Iterator .
collectFirst
// seq.collect{case P => ???}.headOption // seq.collectFirst{case P => ???}
, .
- .
- :
Set , Map , Iterator .
4.10
filter
// seq.filter(p1).filter(p2) // seq.filter(x => p1(x) && p2(x))
( filter ), .
, ( ), : seq.view.filter(p1).filter(p2).force .
p1 p2 .- :
Set , Option , Map , Iterator .
map
// seq.map(f).map(g) // seq.map(f.andThen(g))
, .
, view ( ), : seq.view.map(f).map(g).force .
f g .- :
Set , Option , Map , Iterator .
// seq.sorted.filter(p) // seq.filter(p).sorted
â . , .
map
() , ( List ). , , , .
.
Set
( ), .
slice
// seq.drop(x).take(y) // seq.slice(x, x + y)
, . , .
: Set , Map , Iterator .
splitAt
( List , Stream ), - , .
: Set , Map .
span
, .
p .- :
Set , Map , Iterator .
partition
// val seq1 = seq.filter(p) val seq2 = seq.filterNot(p) // val (seq1, seq2) = seq.partition(p)
-,
p .- :
Set , Map , Iterator .
takeRight
// seq.reverse.take(n).reverse // seq.takeRight(n)
( , ).
flatten
// (seq: Seq[Seq[T]]) seq.reduce(_ ++ _) seq.fold(Seq.empty)(_ ++ _) seq.flatMap(identity) // seq.flatten
: .
: Set , Option , Iterator .
flatMap
// (f: A => Seq[B]) seq.map(f).flatten // seq.flatMap(f)
- . , .
: Set , Option , Iterator .
map
// seq.map(???) // // seq.foreach(???)
, map . , .
: Set , Option , Map , Iterator .
unzip
// (seq: Seq[(A, B]]) seq.unzip._1 // seq.map(_._1)
, - .
- :
unzip3 . - :
Set , Option , Map , Iterator .
( ).
1) .
// seq.map(f).flatMap(g).filter(p).reduce(???) // seq.view.map(f).flatMap(g).filter(p).reduce(???)
reduce , , : reduceLeft , reduceRight , fold , foldLeft , foldRight , sum , product , min , max , head , headOption , last , lastOption , indexOf , lastIndexOf , find , contains , exists , count , length , mkString , ..
â , , - , GC. , ( map , flatMap , filter , ++, ..) «» ( Stream ) , , .
(view) â , , :
, view .
2) , .
, - â force ( ):
// seq.map(f).flatMap(g).filter(p) // seq.view.map(f).flatMap(g).filter(p).force
â , , , withFilter :
seq.withFilter(p).map(f)
"for comprehensions". , â , (, ). , ( ) ( veiw force )
, withFilter - .
3) .
// seq.map(f).flatMap(g).filter(p).toList // seq.view.map(f).flatMap(g).filter(p).toList
force -, .
« + ». breakOut :
seq.map(f)(collection.breakOut): List[T]
, :
- (, , ),
- (, ,
map , flatMap , filter , fold , ..), - ( , Scala).
, , breakOut .
.
- (
f g ) ( p ) ( , , ). - :
Set , Map .
Scala « », « » (âassignment operatorsâ) â x <op>= y x = x <op> y , : <op> (: + , - , .). , <op> : , - (.. , ). :
// list = x :: list list1 = list2 ::: list1 stream = x
.
Set , Map , Iterator ( ).
// seq.foldLeft(Set.empty)(_ + _) seq.foldRight(List.empty)(_ :: _) // seq.toSet seq.toList
, , . , , .
: Set , Option , Iterator .
toSeq .
- , Seq(...) ( , Vector ), toSeq ( Stream , Iterator view ) . TraversableOnce.toSeq Stream , , . , , .
:
val source = Source.fromFile("lines.txt") val lines = source.getLines.toSeq source.close() lines.foreach(println)
IOException , , .
, toStream , , toVector toSeq .
// (seq: Seq[String]) seq.reduce(_ + _) seq.reduce(_ + separator + _) seq.fold(prefix)(_ + _) seq.map(_.toString).reduce(_ + _) // seq: Seq[T] seq.foldLeft(new StringBuilder())(_ append _) // seq.mkString seq.mkString(prefix, separator, "")
, StringBuilder .
- :
reduceLeft , reduceRight , foldLeft , foldRight . - :
Set , Option , Iterator .
5. (Sets)
. , .
sameElements
( ), .
sameElements , , .
, : , LinkedHashSet .
: Map .
Set -
// (set: Set[Int]) Seq(1, 2, 3).filter(set(_)) Seq(1, 2, 3).filter(set.contains) // Seq(1, 2, 3).filter(set)
Set[T] Function1[T, Boolean] , .
// set1.filter(set2.contains) set1.filter(set2) // set1.intersect(set2) // set1 & set2
, .
, , .
// set1.filterNot(set2.contains) set1.filterNot(set2) // set1.diff(set2) // set1 &~ set2
, , .
, , .
6. Options
Option Scala , ( ..) , , - .
Option. , , Option API.
6.1
Option None
// option == None option != None // option.isEmpty option.isDefined
, , , Option .
, Option[T] T , scalac ( ), .
Option Some
// option == Some(v) option != Some(v) // option.contains(v) !option.contains(v)
.
isInstanceOf
// option.isInstanceOf[Some[_]] // option.isDefined
.
// option match { case Some(_) => true case None => false } option match { case Some(_) => false case None => true } // option.isDefined option.isEmpty
, â . , .
: Seq , Set .
,
// !option.isEmpty !option.isDefined !option.nonEmpty // seq.isDefined seq.isEmpty seq.isEmpty
, â , .
, : isDefined ( option) nonEmpty ( ). , Option .
6.2 Null
null , Option
// if (v != null) Some(v) else None // Option(v)
.
null
// option.getOrElse(null) // option.orNull
, .
6.3
, , Option .
, Option , , « Option â map , flatMap , filter foreach ». , "check & get" ( ) , if .
â , «» :
- ,
NoSuchElementException MatchError
.
getOrElse
// if (option.isDefined) option.get else z option match { case Some(it) => it case None => z } // option.getOrElse(z)
orElse
// if (option1.isDefined) option1 else option2 option1 match { case Some(it) => Some(it) case None => option2 } // option1.orElse(option2)
exists
// option.isDefined && p(option.get) if (option.isDefined) p(option.get) else false option match { case Some(it) => p(it) case None => false } // option.exists(p)
forall
// option.isEmpty || (option.isDefined && p(option.get)) if (option.isDefined) p(option.get) else true option match { case Some(it) => p(it) case None => true } // option.forall(p)
contains
// option.isDefined && option.get == x if (option.isDefined) option.get == x else false option match { case Some(it) => it == x case None => false } // option.contains(x)
foreach
// if (option.isDefined) f(option.get) option match { case Some(it) => f(it) case None => } // option.foreach(f)
filter
// if (option.isDefined && p(option.get)) option else None option match { case Some(it) && p(it) => Some(it) case _ => None } // option.filter(p)
map
// if (option.isDefined) Some(f(option.get)) else None option match { case Some(it) => Some(f(it)) case None => None } // option.map(f)
flatMap
// (f: A => Option[B]) if (option.isDefined) f(option.get) else None option match { case Some(it) => f(it) case None => None } // option.flatMap(f)
6.4
map getOrElse fold
// option.map(f).getOrElse(z) // option.fold(z)(f)
( z â ), . (- Scala), .
, - , , .
exists
// option.map(p).getOrElse(false) // option.exists(p)
( Option ). getOrElse .
flatten
// (option: Option[Option[T]]) option.map(_.get) option.getOrElse(None) // option.flatten
.
Option Seq
// option.map(Seq(_)).getOrElse(Seq.empty) option.getOrElse(Seq.empty) // option: Option[Seq[T]] // option.toSeq
, .
7.
, , .
// map.find(_._1 == k).map(_._2) // map.get(k)
, , - , Map (, ) â . , .
get ,
// Before map.get(k).get // After map(k)
Option , (raw) .
lift get
// Before map.lift(k) // After map.get(k)
, ( ), . lift , ( Map PartialFunction ) .
get getOrElse
// map.get(k).getOrElse(z) // map.getOrElse(k, z)
, . z , .
Map -
// (map: Map[Int, T]) Seq(1, 2, 3).map(map(_)) // Seq(1, 2, 3).map(map)
Map[K, V] Function1[K, V], .
// map.map(_._1) map.map(_._1).toSet map.map(_._1).toIterator // map.keys map.keySet map.keysIterator
( ).
// map.map(_._2) map.map(_._2).toIterator // map.values map.valuesIterator
( ).
filterKeys
// map.filterKeys(p) // map.filter(p(_._1))
filterKeys - . , filterKeys . , , , , filterKeys(p).groupBy(???) .
«» ( , ) â , - .
filterKeys , , , - , . withKeyFilter ( withFilter ).
, .
, filterKeys ( , ), .
, , ( ) , , :
type MapView[A, +B] = Map[A, B] implicit class MapExt[A, +B](val map: Map[A, B]) extends AnyVal { def withKeyFilter(p: A => Boolean): MapView[A, B] = map.filterKeys(p) }
MapView , , view-. :
def get(k: T) = if (p(k)) map.get(k) else None
mapValues
// map.mapValues(f) // map.map(f(_._2))
, . :
type MapView[A, +B] = Map[A, B] implicit class MapExt[A, +B](val map: Map[A, B]) extends AnyVal { def withValueMapper[C](f: B => C): MapView[A, C] = map.mapValues(f) }
:
def get(k: T) = map.get(k).map(f)
// map.filterKeys(!seq.contains(_)) // map
, .
// map = map + x -> y map1 = map1 ++ map2 map = map - x map = map -- seq // map += x -> y map1 ++= map2 map -= x map --= seq
, , .
8.
Scala , .
:
Scala.
, . , - , . .
翻蚳è
ãã
. ( ). firegurafiku , .