Lists are....
Empty list
Nil //Nil is "The empty list." in Scala //List() (result)
List() //Empty list //List() (result)
List[AnyVal]() //List of numeric values //List() (result)
List.empty[AnyVal]//same as above //List() (result)
Type of an empty list
typeOf(Nil) //scala.collection.immutable.Nil.type (result)
typeOf(List()) //List[Nothing] (result)
typeOf(List[Nothing]()) //List[Nothing] (result)
typeOf(List[Any]()) //List of anything //List[Any] (result)
typeOf(List[String]()) //List of strings //List[String] (result)
typeOf(List.empty[String]) //List of strings //List[String] (result)
Are empty lists equal? Yes.
Nil == List() //true (result)
List() == List[AnyVal]() //true (result)
List[AnyVal]() == List.empty[AnyVal] //true (result)Lists of different types are equal if they're empty
List[Int]() == List[String]() //true (result)
Non-empty lists List of Int's
val int_list = List(1, 2, 3)
typeOf(int_list) //List[Int] (result)List of Strings
val string_list = List("1", "2", "3")
typeOf(string_list) //List[String] (result)
Mixing element type Scala will try to keep most of information about type of elements
List of Strings and Int's
(common type is Any)
val mixed_list_si = List("1", 2, "3")
typeOf(mixed_list_si) //List[Any] (result)List of Int's and Double's
(common type is AnyVal, there's conversion from int to double)
val mixed_list_id = List(1, 2.0, 3)
typeOf(mixed_list_id) //List[Double] (result)List of Int's and BigInt's
(common type is Any)
val mixed_list_ibi = List(1, BigInt(2), 3)
typeOf(mixed_list_ibi) //List[Any] (result)
Getting elements of list
val items = List(1, 2, 3, 4.0)head of list (first element)
items.head // fast, complexity O //1.0 (result)head cannot be used on empty list
List().headOutput
Exception:java.util.NoSuchElementException: head of empty list
head is a 0-th element of list
items(0) == items.head //true (result)last element (we must iterate all elements to get there)
items.last // slow, complexity N //4.0 (result)n-th element (we must iterate n elements to get there)
items(3) // slow, complexity N //4.0 (result)
Size of list size and length are eqivalent. Scala does not keep a counter of elements. We must iterate over all elements count them.
items.size // slow, complexity N //4 (result)
items.length // slow, complexity N //4 (result)
Splitting list into head and tail Split list to head and tail
val items_head::items_tail = items//this will create 2 val's
items_head //1.0 (result)
items_tail //List(2.0, 3.0, 4.0) (result)Empty list cannot be split (no head)
val empty_head::empty_tail = List()Output
Exception:scala.MatchError: List() (of class scala.collection.immutable.Nil$)
val empty_head::empty_tail = List[Int]()Output
Exception:scala.MatchError: List() (of class scala.collection.immutable.Nil$)
Single element list can be split info element and Empty list
5 :: Nil == List[Int](5) //true (result)
val single_head::single_tail = List[Int](5)
single_head //5 (result)
single_tail //List() (result)
Lists are recursive
List items
items //List(1.0, 2.0, 3.0, 4.0) (result)is equivalent to
1.0::(2.0::(3.0::(4.0::(Nil))))Output
List(1.0, 2.0, 3.0, 4.0)
Getting part of list
items //List(1.0, 2.0, 3.0, 4.0) (result)Ignore 2 first elements, take the rest
items.drop(2) //fast //List(3.0, 4.0) (result)Take 3 first elements, ignore the rest
items.take(3) //fast //List(1.0, 2.0, 3.0) (result)
typeOf(items.take(3)) //List[Double] (result)drop and take work with empty lists
List().drop(2) //List() (result)
List().take(2) //List() (result)and with list smaller than given number of elements
items.drop(20) //empty //List() (result)
items.take(20) //all list //List(1.0, 2.0, 3.0, 4.0) (result)take n last elements
items.takeRight(4) //slow //List(1.0, 2.0, 3.0, 4.0) (result)
items.reverse.take(4) //slow //List(4.0, 3.0, 2.0, 1.0) (result)drop n last elements
items.dropRight(4) //slow //List() (result)
items.reverse.drop(4) //slow //List() (result)
Iteration
def funny(x : Double) = x * 2
for(x <- 0 until items.length) yield funny(x)Output
Vector(0.0, 2.0, 4.0, 6.0)
def foo(l : List[Double]) : List[Double]= l match {
case Nil => Nil
case h::t => funny(h)::foo(t)
}
foo(items)OutputList(2.0, 4.0, 6.0, 8.0)
Why not map?
items.map(funny)Output
List(2.0, 4.0, 6.0, 8.0)
Or parallel map?
items.par.map(funny)Output
ParVector(2.0, 4.0, 6.0, 8.0)
Get index of element
items.zipWithIndexOutput
List((1.0,0), (2.0,1), (3.0,2), (4.0,3))
Then we can use map
items.zipWithIndex.map {ei =>
var (element,index) = ei
"items[" + index + "]=" + element}OutputList(items[0]=1.0, items[1]=2.0, items[2]=3.0, items[3]=4.0)
...and partial function to extract item and index
items.zipWithIndex.map{case (item,index) => s"items[$index]=$item"}OutputList(items[0]=1.0, items[1]=2.0, items[2]=3.0, items[3]=4.0)
Joining lists
int_list //List(1, 2, 3) (result)
typeOf(int_list) //List[Int] (result)
string_list //List(1, 2, 3) (result)
typeOf(string_list) //List[String] (result)Join of two lists (list style)
int_list ::: string_list //List(1, 2, 3, 1, 2, 3) (result)
typeOf(int_list ::: string_list) //List[Any] (result)Join of two lists (universal style)
int_list ++ string_list //List(1, 2, 3, 1, 2, 3) (result)
Adding element to list
int_list //List(1, 2, 3) (result)
typeOf(int_list) //List[Int] (result)list-style add as head
100::items //List(100, 1.0, 2.0, 3.0, 4.0) (result)
(100::items).head //100 (result)universal append as head
100+:items //List(100, 1.0, 2.0, 3.0, 4.0) (result)
(100+:items).head //100 (result)universal append as last
items:+200 //List(1.0, 2.0, 3.0, 4.0, 200) (result)
(items:+200).last //200 (result)
Operators
2+:List(3,7) //List(2, 3, 7) (result)is equivalent to
List(3,7).+:(2) //List(2, 3, 7) (result)but
List(3,7):+2 //List(3, 7, 2) (result)is equivalent to
List(3,7).:+(2) //List(3, 7, 2) (result)
Common usecases Create list of length 4, filled with element 3
List.make(4, 3) //List(3, 3, 3, 3) (result)Join list into String
List(5,2,1).mkString(" and ") //5 and 2 and 1 (result)
Join list into String with prefix and postfix
List(5,2,1).mkString("list contains ", " and ", ".") //list contains 5 and 2 and 1. (result)
Remove duplicates from list
List(1,1,0,1,1,0,0,1,2).distinct //List(1, 0, 2) (result)
No comments:
Post a Comment