Scala.16장 | 리스트


16. 리스트

16.1 리스트 리터럴

val fruit = List("apples", "oranges", "pears")
var diag3 =
	List (
		List(1, 0, 0),
		List(0, 1, 0),
		List(0, 0, 1)
    )
var empty = List()

16.2 리스트 타입

16.3 리스트 생성

val fruit = "apples" :: ("oranges" :: ("pears" :: Nil))
var diag3 = (1 :: (0 :: (0 :: Nill))) ::
			(0 :: (1 :: (0 :: Nill))) ::
			(0 :: (0 :: (1 :: Nill))) :: Nil
var empty = Nil

// 두개는 같음
val nums = List(1, 2, 3, 4)
val nums = 1 :: 2 :: 3 :: 4 :: Nil

16.4 리스트 기본 연산

val fruit = List("apples", "oranges", "pears")

// "oranges" 반환
fruit.tail.head
// 삽입 정렬 예시
def isort(xs: List[Int]): List[Int] =
	if (xs.isEmpty) Nil
	else insert(xs.head, isort(xs.tail))
def insert(x: Int, xs: List[Int]): List[Int] =
	if (xs.isEmpty || x <= xs.head) x :: xs
	else xs.head :: insert(x, xs.tail)

16.5 리스트 패턴

val List(a, b, c) = fruit
a: String = apples
b: String = oranges
c: String = pears

//  리스트 원소 갯수를 미리 알 수 없다면
val a :: b :: rest = fruit
a: String = apples
b: String = oranges
rest: List[String] = List(pears)
// 삽입 정렬 예시
def isort(xs: List[Int]): List[Int] = xs match {
	case List()		=> List()
	case x :: xs1 	=> insert(x, isort(xs1))
}
	
def insert(x: Int, xs: List[Int]): List[Int] = xs match {
	case List() 	=> List(x)
	case y :: ys 	=> if (x <= y) x || xs
						else y :: insert(x, ys)
}

16.6 List 클래스의 1차 메소드

어떤 메소드가 함수를 인자로 받지 않는다면 1차 메소드라 부른다.

16.6.1 두 리스트 연결

// xs ::: ys 는 xs의 뒤에 ys의 모든 원소를 붙인다
List(1, 2) ::: List(3, 4, 5)
res0: List[Int] = List(1, 2, 3, 4, 5) 

16.6.2 분할 정복 원칙

:::을 분할 정복 원칙을 이용해 직접 구현할 수 있다

def append[T](xs: List[T], ys: List[T]): List[T] =
	xs match {
      case List() => ys
      case x :: xs1 => x :: append(xs1, ys)
	}

16.6.3 리스트 길이 구하기: length

List(1, 2, 3).length
res3: Int = 3

16.6.4 리스트 양 끝에 접근하기: init와 last

val abcde = List('a', 'b', 'c', 'd', 'e')

abcde.last // Char e
abcde.init // List[Char] = List('a', 'b', 'c', 'd')

16.6.5 리스트 뒤집기: reverse

val abcde = List('a', 'b', 'c', 'd', 'e')

abcde.reverse // List[Char] = List('e', 'd', 'c', 'b', 'a')

16.6.6 접두사와 접미사: drop, take, splitAt

abcde take 2 // List(a, b)

abcde drop 2 // List(c, d, e)

abcde splitAt 2 // List(List(a, b), List(c, d, e))

16.6.7 원소 선택: apply, indices

// 둘은 같다
abcde apply 2
abcde(2)

// 리스트에서 유효한 모든 인덱스의 리스트를 반환
abcde.indices
res0: scala.collection.immutable.Range = Range(0, 1, 2, 3, 4)

잘 사용하지 않는다…

16.6.8 리스트의 리스트를 한 리스트로 반듯하게 만들기: flatten

List(List(1, 2), List(3), List(4, 5)).flatten // List(1, 2, 3, 4, 5)

리스트의 원소가 리스트인 경우에만 가능

16.6.9 두 리스트를 순서쌍으로 묶기: zip, unzip

val zipped = abcde zip List(1, 2, 3) // List((a, 1), (b, 2), (c, 3))

zipped.unzip // List(List(a, b, c), List(1, 2, 3))

16.6.10 리스트 출력하기: toString

abcde.toString
res0: String = List(a, b, c, d, e)

16.6.11 리스트 변환하기: iterator, toArray, copyToArray

val arr = abcde.toArray // Array로 변환

xs copyToArray (arr, start) // start 지점부터 Array로 변환

val it = abcde.iterator
it.next // a
it.nect // b

16.7 List 클래스의 고차 메소드

16.7.1 리스트 매핑

// map
List(1, 2, 3) map (_ + 1)
res0: List[Int] = List(2, 3, 4)

// flatmap
val words = List("the", "quick", "brown")
words map (_.toList) // List(List(t, h, e), List(q, u, i, c, k), List(b, r, o, w, n))
words flatmap (_.toList) // List(t,h,e,q,u,i,c,k,b,r,o,w,n)

// foreach
List(1, 2, 3, 4, 5) foreach (sum += _)

16.7.2 리스트 걸러내기

// filter
List(1, 2, 3, 4, 5) filter (_ % 2 == 0) // List(2, 4)

// partition (앞엔 true, 뒤엔 false)
List(1, 2, 3, 4, 5) partition (_ % 2 == 0) // (List(2, 4), List(1, 3, 4))

// find (filter와 동일하지만 첫번째 원소만 반환)
List(1, 2, 3, 4, 5) filter (_ % 2 == 0) // 2

16.7.3 리스트 폴드: /:과 :\

z /: List(a, b, c) (op) 는 op(op(op(z, a), b), c)와 같다. z는 초기 시작값 xs는 폴드할 대상 리스트, op는 이항 연산자.

// 예시
def sum(xs: List[Int]): Int = (0 /: xs) (_ + _) // 모든 원소의 합
def product(xs: List[Int]): Int = (1 /: xs) (_ * _) // 모든 원소의 곱

16.8 List 객체의 메소드

List.apply(1, 2, 3) // List(1, 2, 3)

List.Range(1, 5) // List(1, 2, 3, 4, 5)
List.Range(1, 9, 2) // List(1, 3, 5, 7,)
List.Range(9, 1, -3) // List(9, 6, 3)

List.fill(5)('a') // List('a', 'a', 'a', 'a', 'a')

List.tabulate(5) (n => n*n) // List(0, 1, 4, 9, 16)
List.tabulate(5, 5) (_ * _) // List(List(0, 0, 0, 0, 0),
									List(0, 1, 2, 4, 4),
									List(0, 2, 4, 6, 8),
									List(0, 3, 6, 9, 12),
									List(0, 4, 8, 12, 16))
									
List.concat(List('a', 'b'), List('c')) // List(a, b, c)

16. 9 여러 리스트를 함께 처리하기

(List(10, 20), List(3, 4, 5)).zipped.map(_ * _) // List(30, 80)