Last active
May 11, 2017 21:00
-
-
Save nobitagit/dd3668ba727288aff63fbc6cd2fa6471 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ARRAYS | |
| // Arrays are immutable fixed length collections | |
| // ArrayBuffers have to be imported and are mutable dynamic length collections | |
| import scala.collection.mutable.ArrayBuffer | |
| val arrB = new ArrayBuffer[Int] | |
| // Add an element | |
| arrB += 1 | |
| // Add more elements in one go | |
| arrB += (2,3,4,5) | |
| // concat another Array | |
| arrB ++= Array(6,7,8) | |
| // remove the last 4 elements | |
| arrB.trimEnd(4) | |
| // insert items | |
| arrB.insert(1, 4, 5, 7) // (insert after the 1st index the list of int 4,5,7) | |
| // Array iteration | |
| for (x <- 0 until arrB.length) println(x) | |
| // x will be the index in this case | |
| // note: until means range "NOT INCLUDING" the provided argument. | |
| // Its is actually a function in the form of 0.until(10) | |
| // Also accepts a second argument which is the step | |
| 20.until(10, -2) | |
| // which is also: | |
| 20 until 10 by -2 | |
| // A shorter method is | |
| for (e <- arrB) println(e) | |
| // which is the same as | |
| for (x <- 0 until arrB.length) println(arrB(x)) | |
| // Array transformation | |
| for (elem <- arrB) yield 2 * elem | |
| // returns a new Array or ArrayBuffer, depending on the type of the input | |
| // To perform on condition add a GUARD | |
| for (elem <- arrB if elem % 2 == 0) yield 2 * elem | |
| // Array has methods that can be used in place of "for..yeld" blocks | |
| // if that is too imperative for our taste | |
| arrB.filter(_ % 2 == 0).map(_ * 2) | |
| // computes the same thing as above in a more declarative way | |
| // Multidimensional arrays | |
| val matrix = Array.ofDim[Double](3,4) | |
| // An array of Doubles of 3 rows and 4 columns, initialised with all 0.0 | |
| [ | |
| [0.0, 0.0, 0.0, 0.0], | |
| [0.0, 0.0, 0.0, 0.0], | |
| [0.0, 0.0, 0.0, 0.0] | |
| ] | |
| // Given an array of integers, produce a new array that contains all positive | |
| // values of the original array, in their original order, followed by all values that | |
| // are zero or negative, in their original order. | |
| import scala.collection.mutable.ArrayBuffer | |
| val arr = Array(1,2,-4,-7,3,2,-4,0) | |
| val arrBuff = new ArrayBuffer[Int] | |
| arrBuff ++= (for (x <- arr if x > 0) yield x) | |
| arrBuff ++= (for (x <- arr if x <= 0) yield x) | |
| arrBuff.toArray // -> Array[Int] = Array(1, 2, 3, 2, -4, -7, -4, 0) | |
| // Sort this array | |
| // DESC | |
| arrBuff.sortWith(_ > _) | |
| // ASC | |
| arrBuff.sortWith(_ < _) | |
| // Make a collection of all time zones returned by java.util.TimeZone.getAvailableIDs | |
| // that are in America. Strip off the "America/" prefix and sort the result. | |
| val tzs = java.util.TimeZone.getAvailableIDs | |
| tzs | |
| .filter(_.startsWith("America/")) | |
| .map(_.stripPrefix("America/")) | |
| .sortWith(_ < _) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // MAPS | |
| // - Immutable or mutable | |
| // - They are collections of pairs | |
| // A pair | |
| ("John", 35) | |
| // A map | |
| Map("John" -> 35) | |
| // A map with multiple pairs | |
| Map("John" -> 35, "Lisa", -> 28) | |
| val myMap = Map("John" -> 35) | |
| // myMap: scala.collection.immutable.Map[String,Int] = Map(John -> 35) | |
| val myMapMutable = scala.collection.mutable.Map("John" -> 35) | |
| // myMapMutable: scala.collection.mutable.Map[String,Int] = Map(John -> 35) | |
| // Immutable maps can be extended by concatenation and reassigning to a new var | |
| val newMap = myMap + ("Thais" -> 41) | |
| // newMap: scala.collection.immutable.Map[String,Int] = Map(john -> 35, Thais -> 41) | |
| // If instead of using a "val" we would have used a "var" when assigning myMap | |
| // the first time we could have just reassigned newMap back to it | |
| myMap = myMap + ("Thais" -> 41) | |
| // Remove an item | |
| myMap = myMap - "Thais" | |
| // Mutate a mutable Map | |
| myMapMutable("Glenn") = 29 | |
| myMapMutable += ("Niahm" -> 19, "Cole" -> 31) | |
| // Access a map | |
| myMap("John") | |
| myMap.contains("John") | |
| // Safe getter with fallback to avoid an exception | |
| myMap.getOrElse("John", 0) | |
| // Looping over a Map | |
| for ((k, v) <- myMap) ... | |
| // Get only keys or values | |
| myMap.keySet | |
| myMap.values | |
| // TUPLES | |
| var myTpl = ("Cabbage", 2.99, 4) | |
| // myTpl: (String, Double, Int) = (Cabbage,2.99,4) | |
| // Class[_ <: (String, Double, Int)] = class scala.Tuple3 | |
| myTpl._1 // "Cabbage" | |
| myTpl._2 // 2.99 | |
| // Note that this method is NOT zero based | |
| // # Destructuring via pattern matching. | |
| // Note that _ is for values we don't need (skipping it throws an error) | |
| val (extract1, extract2, _) = myTpl | |
| // extract1: String = Cabbage | |
| // extract2: Double = 2.99 | |
| // Some use cases for tuples | |
| val names = Array("John", "Linda", "Fran") | |
| val ages = Array(32,24,25) | |
| val people = names.zip(ages) | |
| // people is now a tuple, we can covert to Map if needed | |
| names.zip(ages).toMap | |
| // Loope over results | |
| for ((n, a) <- people) ... | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // CLASSES | |
| // | |
| // Classes can have nested classes | |
| import scala.collection.mutable.ArrayBuffer | |
| class Department { | |
| // Item will be a nested class belonging to that particular | |
| // instance of the Department class | |
| class Item(val name: String = "Unnamed Item") { | |
| val relatedItems = new ArrayBuffer[Item] | |
| } | |
| private var items = new ArrayBuffer[Item] | |
| def addItem(name: String) = { | |
| val item = new Item(name) | |
| items += item | |
| item | |
| } | |
| } | |
| val phones = new Department | |
| val laptops = new Department | |
| val iphone = phones.addItem("iPhone") | |
| val nokia = phones.addItem("Nokia") | |
| iphone.relatedItems += nokia // it works | |
| val surface = laptops.addItem("Surface") | |
| iphone.relatedItems += surface // (error: type mismatch;) because it does not belong to the same nested class | |
| // If instead we want to be able to cross reference across parent classes we can use a | |
| // COMPANION OBJECT | |
| // (use :paste mode in REPL if testing this snippet) | |
| object Department { | |
| class Item(val name: String = "Unnamed Item") { | |
| val relatedItems = new ArrayBuffer[Item] | |
| } | |
| } | |
| class Department { | |
| private var items = new ArrayBuffer[Department.Item] | |
| def addItem(name: String) = { | |
| val item = new Department.Item(name) | |
| items += item | |
| item | |
| } | |
| } | |
| val bookstore = new Department | |
| val recordstore = new Department | |
| val book1 = bookstore.addItem("Mick Jagger: biography") | |
| val book2 = bookstore.addItem("The history of Rock") | |
| val record1 = recordstore.addItem("Sticky Fingers") | |
| book1.relatedItems += book2 | |
| book2.relatedItems += record1 // it works | |
| // Improve the Counter class in Section 5.1, “Simple Classes and Parameterless Methods,” | |
| // on page 49 so that it doesn’t turn negative at Int.MaxValue. | |
| class Counter { | |
| private var value = BigInt(0) | |
| def increment() { | |
| value += 1 | |
| } | |
| def setToMaxIntLimit() { | |
| value = Int.MaxValue | |
| } | |
| def current = value | |
| } | |
| // Write a class BankAccount with methods deposit and withdraw, and a read-only property balance. | |
| class BankAccount { | |
| var _balance = 0 | |
| def deposit(amount: Int) { | |
| _balance += amount | |
| } | |
| def withdraw(amount: Int) { | |
| _balance -= amount | |
| } | |
| def balance = _balance | |
| } | |
| // 3. Write a class Time with read-only properties hours and minutes and a method | |
| // before(other: Time): Boolean that checks whether this time comes before the | |
| // other. A Time object should be constructed as new Time(hrs, min), where hrs is in | |
| // military time format (between 0 and 23). | |
| class Time(val hrs: Int, val min: Int) { | |
| require(hrs >= 0 && hrs < 24) | |
| require(min >= 0 && min < 60) | |
| def before(other: Time) : Boolean = { | |
| (hrs < other.hrs || (hrs == other.hrs && min < other.min)) | |
| } | |
| } | |
| // 4. Reimplement the Time class from the preceding exercise so that the internal representation | |
| // is the number of minutes since midnight (between 0 and 24 * 60 - 1). | |
| // Do not change the public interface. That is, client code should be unaffected by your change. | |
| class Time(val hrs: Int, val min: Int) { | |
| require(hrs >= 0 && hrs < 24) | |
| require(min >= 0 && min < 60) | |
| _time = hrs * 60 + min | |
| def time = _time | |
| def before(other: Time) : Boolean = { | |
| (_time < other.time) | |
| } | |
| } | |
| // 5. Make a class Student with read-write JavaBeans properties name (of type String) and | |
| // id (of type Long). What methods are generated? (Use javap to check.) | |
| // Can you call the JavaBeans getters and setters in Scala Should you?” | |
| import scala.beans._ | |
| class Person(@BeanProperty var firstName: String, @BeanProperty var id: Long) {} | |
| // See: http://alvinalexander.com/scala/how-to-disassemble-decompile-scala-source-code-javap-scalac-jad | |
| // Save to a file, say test.scala then compile: | |
| // > scalac test.scala | |
| // then run: | |
| // javap Person | |
| /* | |
| public class Person { | |
| public java.lang.String firstName(); | |
| public void firstName_$eq(java.lang.String); | |
| public long id(); | |
| public void id_$eq(long); | |
| public java.lang.String getFirstName(); | |
| public void setFirstName(java.lang.String); | |
| public long getId(); | |
| public void setId(long); | |
| public Person(java.lang.String, long); | |
| } | |
| */ | |
| // So we can make: | |
| val john = new Person("John", 123) | |
| john.getFirstName | |
| // > John | |
| john.setFirstName("Louis") | |
| john.getFirstName | |
| // > Louis | |
| // 6. In the Person class of Section 5.1, “Simple Classes and Parameterless Methods,” on page 49, | |
| // provide a primary constructor that turns negative ages to 0. | |
| class Person(val age: Int) { | |
| if (age < 0) age = 0 | |
| } | |
| // 7. Write a class Person with a primary constructor that accepts a string containing | |
| // a first name, a space, and a last name, such as new Person("Fred Smith"). Supply | |
| // read-only properties firstName and lastName. Should the primary constructor | |
| // parameter be a var, a val, or a plain parameter? Why? | |
| class Person1(val fullName: String) { | |
| val split = fullName.split(" ") | |
| val firstName : String = split(0); | |
| val lastName : String = split(1); | |
| } | |
| // Actually I did wrong, it should just be class Person(fullName: String) | |
| // since no method uses it. This is how it should be done in this case. | |
| class Person2(fullName: String) { | |
| val split = fullName.split(" ") | |
| val firstName : String = split(0); | |
| val lastName : String = split(1); | |
| } | |
| // To test this out, try instatiating new Person1("John Smith") | |
| // and then access person.fullName. This will work, while | |
| // the same is not true for an insatnce of Person2, which will throw. | |
| // This concept is explained in 5.7 The Primary Contructor | |
| // 8. Make a class Car with read-only properties for manufacturer, model name, | |
| // and model year, and a read-write property for the license plate. Supply four | |
| // constructors. All require the manufacturer and model name. Optionally, | |
| // model year and license plate can also be specified in the constructor. If not, | |
| // the model year is set to -1 and the license plate to the empty string. Which | |
| // constructor are you choosing as the primary constructor? Why? | |
| // Let's recap a few basics. Defining Car this way | |
| class Car(var manufacturer: String) {} | |
| // Scala sets up a private field called manufacturer, with a getter and a setter method for it | |
| // We can in fact do: | |
| var car = new Car("Fiat") | |
| car.manufacturer | |
| // > "Fiat" | |
| car.manufacturer = "Volvo" // | |
| // > "Volvo" | |
| // If we save the class definition to a file called Car.class | |
| // and run `scalac car.scala javap -private Car` we'll See | |
| //> javap -private Car.class | |
| //> Compiled from "car.scala" | |
| public class Car { | |
| private java.lang.String manufacturer; // <= private value | |
| public java.lang.String manufacturer(); // <= getter | |
| public void manufacturer_$eq(java.lang.String); // <= setter | |
| public Car(java.lang.String); // <= constructor | |
| } | |
| // NOTE: if the field is a val only a getter is set up, though | |
| class Car(val manufacturer: String) {} | |
| // equates | |
| public class Car { | |
| private final java.lang.String manufacturer; | |
| public java.lang.String manufacturer(); | |
| public Car(java.lang.String); | |
| } | |
| // ## Primary Constructor (P.C.) and Auxiliary constuctors (A.C.) | |
| class Song { | |
| private var title = "" // <= PC | |
| private var length = 0 // <=// | |
| def this(name: String) { // <= A.C. #1 | |
| this() // <= call the primary constructor | |
| this.title = title | |
| } | |
| def this(title: String, length: Int) { // <= A.C. #2 | |
| this(name) // <= call the A.C # 1 | |
| this.length = length | |
| } | |
| } | |
| // 10. Consider the class: | |
| class Employee(val name: String, var salary Double) { | |
| def this() { this("John Public", 0.0) } | |
| } | |
| // Rewrite it to use explicit fields and a default primary constructor. | |
| // Which form do you prefer? Why? | |
| class Employee(val name: String = "John Public", val salary: Double = 0.0) {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Write a function that takes a character and returns the next character in the alphabet | |
| def nextChar(char: Char) : Char = { | |
| (char + 1).toChar | |
| } | |
| // Set up a map of prices for a number of gizmos that you covet. | |
| // Then produce a second map with the same keys and the prices at a 10 percent discount. | |
| var gizmos = Map("S7" -> 510.00, "Glasses" -> 300.00, "RayBan" -> 320.00) | |
| for ((k, v) <- gizmos) yield (k, v - (v / 10)) | |
| // scala.collection.immutable.Map[String,Double] = Map(S7 -> 459.0, Glasses -> 270.0, RayBan -> 288.0) | |
| // or... | |
| gizmos.map(t => (t._1, t._2 - (t._2 / 10))) | |
| // scala.collection.immutable.Map[String,Double] = Map(S7 -> 459.0, Glasses -> 270.0, RayBan -> 288.0) | |
| // Ch4 | |
| // Write a program that reads words from a file. Use a mutable map to count | |
| // how often each word appears. | |
| val in = new java.util.Scanner(new java.io.File("myfile.txt")) | |
| var hashMap = scala.collection.mutable.Map[String, Int]() | |
| while (in.hasNext()) { | |
| val w = in.next() | |
| hashMap(w) = hashMap.getOrElse(w, 0) + 1 | |
| } | |
| for ((k, v) <- hashMap) println(k, v) | |
| // Repeat the preceding exercise with an immutable map. | |
| val in = new java.util.Scanner(new java.io.File("myfile.txt")) | |
| var hashMap = Map[String, Int]() | |
| while (in.hasNext()) { | |
| val w = in.next() | |
| val occ = hashMap.getOrElse(w, 0) + 1 | |
| hashMap = hashMap + (w -> occ) | |
| } | |
| for ((k, v) <- hashMap) println(k, v) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment