[정리] Scala 정리(2) - 컬렉션

3 분 소요

스칼라 학교!을 개인적으로 정리한 것입니다.

기본 데이터 구조

리스트

val numbers = List(1,2,3,4)

집합

val numbers = Set(1,2,3) // duplication is not allowed 

튜플

val hostPort = ("localhost",80)

hostPort._1 // return "localhost"
hostPort._2 // returns 80

// pattern matching using tuple
hostPort match {
  case ("localhost", port) => ...
  case (host, port) => ...
}

1->2 // returns (Int, Int) = (1,2)

Map(1->2)
Map("foo" -> "bar")
Map(1->2, 3->4)

옵션(Option)

어떤 객체가 존재하거나 존재하지 않는 것을 나타낸다.

scala> val numbers = Map("one" -> 1, "two" -> 2)
//numbers: scala.collection.immutable.Map[java.lang.String,Int] = Map(one -> 1, two -> 2)

scala> numbers.get("two")
//res0: Option[Int] = Some(2), key가 있는 경우

scala> numbers.get("three")
// res1: Option[Int] = None, key가 없는 경우

// None값 처리 예시
val result = res1.getOrElse(0) * 2
// 패턴매칭
val result = res1 match { case Some(n) => n * 2 case None => 0 }

함수 콤비네이터

map

numbers=List(1,2,3,4)
numbers.map((i: Int) => i * 2)
// or 
def timesTwo(i: Int): Int = i * 2
numbers.map(timesTwo _)

foreach

map과 비슷하지만 아무것도 반환하지 않는다. 즉 값의 반환이 아닌 상태 변화에 초점을 두고 있다.

numbers.foreach((i: Int) => i * 2)

filter

numbers.filter((i:Int) => i%2==0)

zip

두 리스트들의 원소들의 쌍(튜플)으로 이루어진 단일 리스트를 반환한다.

scala> List(1, 2, 3).zip(List("a", "b", "c"))
// returns res0: List[(Int, String)] = List((1,a), (2,b), (3,c))

find

주어진 함수를 만족하는 가장 첫 원소를 반환

scala> numbers.find((i: Int) => i > 5)
// res0: Option[Int] = Some(6)

drop과 dropWhile

  • drop: 첫 i 개의 원소를 제거한다.
  • dropWhile: 조건에 맞는 첫 원소를 제거한다. ```scala scala> numbers.drop(5) // res0: List[Int] = List(6, 7, 8, 9, 10) // 5개의 원소 제거

scala> numbers2.dropWhile( _ !=5) // res7: List[Int] = List(5, 6, 7, 8, 9, 10) // 인수로 들어온 식이 거짓이 되는 순간 까지 제거

 
### foldLeft, foldRight

```scala
/* foldLeft */
numbers.foldLeft(0) { 
  (m: Int, n: Int) => println("m: " + m + " n: " + n); m + n 
}
// m: 0 n: 1    <- 초기값 왼쪽으로 들어감
// m: 1 n: 2    
// m: 3 n: 3    <- m+n   (이전 계산의 합이) 
// m: 6 n: 4    <-    =m (왼쪽 인수로 들어감)
// m: 10 n: 5
// m: 15 n: 6
// m: 21 n: 7
// m: 28 n: 8
// m: 36 n: 9
// m: 45 n: 10
// res0: Int = 55

/* foldRight */
numbers.foldRight(0) { 
  (m: Int, n: Int) => println("m: " + m + " n: " + n); m + n 
}
// m: 10 n: 0     <- 초기값 오른쪽으로 들어감
// m: 9 n: 10
// m: 8 n: 19     <- m+n   (이전 계산의 합이) 
// m: 7 n: 27     <-    =n (오른쪽 인수로 들어감)
// m: 6 n: 34
// m: 5 n: 40
// m: 4 n: 45
// m: 3 n: 49
// m: 2 n: 52
// m: 1 n: 54
// res0: Int = 55

flatten

리스트를 합침

scala> List(List(1, 2), List(3, 4)).flatten
// res0: List[Int] = List(1, 2, 3, 4)

flatMap

mapflatten을 합친 것이다.

scala> val nestedNumbers = List(List(1, 2), List(3, 4))
// nestedNumbers: List[List[Int]] = List(List(1, 2), List(3, 4))

scala> nestedNumbers.flatMap(x => x.map(_ * 2))
// res0: List[Int] = List(2, 4, 6, 8)

// using flatten after map, result is same
scala> nestedNumbers.map((x: List[Int]) => x.map(_ * 2)).flatten

일반적인 함수 콤비네이터

fold를 기본으로 작성될 수 있다.

def myMap(numbers: List[Int], fn: Int => Int): List[Int] = {
  numbers.foldRight( List[Int]() )/* 초기값 */ { 
    (x: Int, xs: List[Int]) => fn(x) :: xs // ::는 리스트 합치기
  }
}

Map?

val extensions = Map("steve" -> 100, "bob" -> 101, "joe" -> 201)
// _2로 직접 접근 --> BAD!
extensions.filter((namePhone: (String, Int)) => namePhone._2 < 200)

// using Pattern Matching
extensions.filter({case (name, extension) => extension < 200})

댓글남기기