(4 :: List(1,2,3).reverse).reverse
- 새 리스트로 추가한다.
List(1,2,3) ::: List(4)
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
이 시리즈는 스칼라언어의 창시자인 마틴 오더스키가 직접 저술한 Programming in Scala (2판)
을 참고로 하여 정리할 예정입니다. 잘못된 점이 있으면 지적해주시면 바로 수정하겠습니다.
스칼라의 배열이 값을 변경 할 수 있는 순서가 정해진 시퀀스라면 스칼라의 리스트는 기본적으로 값을 변경 할 수 없는 시퀀스입니다.
배열 생성과 비슷합니다.
val x = List.range(1, 10) // 범위로 List(1, 2, 3, 4, 5, 6, 7, 8, 9)
val x = List.fill(3)("foo") // List(foo, foo, foo)
List.tabulate(5)(n => n * n) // List(0, 1, 4, 9, 16)
자바)
List b = new List; <-- 안된다 . 인터페이스임
String a[] = new String[2];
List b = Arrays.asList(a);
List<String> list =new ArrayList<String>();
List<String> list =new LinkedList<String>();
코틀린)
val z = List() <-- 안된다 . 인터페이스임
val a = listOf("hi", "bye")
val b = List<String>(2, {it -> it.toString()})
val c = mutableListOf<String>()
val a = List(1,2,3)
a(2)
두개의 리스트 합치기
두개의 리스트를 합쳐보겠습니다.
val a = List(1,2)
val b = List(3,4)
val c = a ::: b
이렇게 합니다.
::: 는 두개의 리스트를 합쳐주는 메소드 입니다.
val d = a ++ b 이렇게 할 수도 있습니다. ( ::: 는 오로지 리스트에서만 사용)
Scala list concatenation, ::: vs ++
리스트 앞에 요소 추가
그럼 앞에다가 요소하나를 붙여주는 메소드는 무엇일까요?
List(1,2) 앞에다가 0 을 붙여서 (0,1,2) 로 만드는 방법 말이죠.
그건 :: 입니다. 콜론이 2개짜리네요.
근데 여기서 생각해 볼것은 서두에 List 는 변경 불가능하다고 했는데 앞에 숫자를 붙히다니?
무슨 소리하는지 의심스러울거 같은데요.
예를 한번 봅시다.
val a = List(1,2)
val b = 0 :: a
이건데요.
네 a 를 바꾼게 아니었습니다. a 앞에 0 을 추가한 또 다른 b 라는 List 를 만든거에요.
즉 무엇을 변경해서 쓰려면, 기존것은 냅두고 기존것을 이용해서 새것을 만들어서 쓰라는 말입니다.
또 궁금한게 있을거 같은데요.
도대체 0 :: a 를 하는데 어떻게 a 앞에 0 이 들어가게 되는지 말이죠.
그 이유는
:: 메소드는 0 의 메소드가 아니라 a 의 메소드입니다. 근데 앞에 있는 이유는
그냥 규칙입니다. -.-;;
우리의 마틴오더스키씨는 아주 많은걸 자신이 만든 언어에 쑤셔 넣었습니다.
그 규칙은 이름이 콜론(:) 으로 끝나는 메소드는 오른쪽 피연산자의 것으로 호출한다. 라고 합니다.
따라서
0 :: a 는 a.::(0) 이 되는 것입니다.
리스트 뒤에 요소 추가
그럼 뒤에 추가하는것은 무엇일까요?
:+ 입니다.
예를들어
val a = List(1,2)
val b = a :+ 2
이런거죠.
하지만 웬간하면 이걸 쓰지마세요.
뒤에 추가하는 연산은 리스트의 길이만큼 오래 걸린다고 합니다.
이걸 효율적으로 하려면
일단 리스트를 뒤집고, 앞에다가 원소를 추가한후에 다시 뒤집으세요.
(4 :: List(1,2,3).reverse).reverse
- 새 리스트로 추가한다.
List(1,2,3) ::: List(4)
입니다.
List 의 다양한 메소드들
자 이런 변경 불가능한 List 를 사용해서 편하게 작업할 수 있는 방법들이 무지 많습니다.
문제는 편해지려면 이거 공부하고 외워야한다는거죠. 러닝커브가 올라갑니다. ;;
대표적인 몇가지만 살펴보도록 하겠습니다.
// 빈리스트
List()
// 두번째 인덱스 원소 얻기
val a = List(1,2,3)
a(2)
// 두번째 원소 까지 제거
val a = List(1,2,3)
val b = a.drop(2)
결과 : List(3)
눈여겨 볼것은 자체의 원소를 제거한게 아니라, 원소 제거한 새로운 리스트를 반환합니다.
// 요소중 길이가 3인것의 개수를 센다
val a = List ("hello", "world", "boy")
a.count(s=> s.length == 3)
s=> s.length == 3 은 람다식이죠? 인자가 s 인 함수란 야그입니다. 다음과 같아요
bool func ( s ) {
return s.length == 3
}
// 리스트의 각 원소를 변경하여 새 리스트를 반환합니다. 여기선 각 문자열 뒤에 X 를 붙힙니다.
val a = List ("hello", "world", "boy")
val b = a.map(s => s + "X")
자 다양한 메소드를 보았는데요. 이거 말고도 더 있긴합니다. 근데 여기서 생각해 봐야할것은 메소드가 많구나~~ 이게 아닙니다.
이런 메소드를 사용함으로써 var 를 안쓰게 됬다는겁니다. var 은 변경 가능한 변수를 만들때 씁니다.
예를들어
위에서 count 같은 경우 대략 함수를 만들어 보면
def count( all : Seq[String] ):Int = {
var temp = 0
for ( one <- all ) {
if ( one.length == 4 )
temp = temp + 1
}
temp
}
이렇게 되잖습니까? 위에 보면 var 가 사용되었네요. 스칼라에서는 var 를 사용하지 말도록 합시다!!! (마틴오더스키는 var, val 둘다 만들어서 알아서 적재적소에 쓰이길 바랬지만 , 제 글을 보시는 분들은 절대로 var 를 안쓰는 방향으로 '만' 생각하자구요. )
* 재귀를 활용한 count 함수
def count(list: Seq[String]): Int = {
@tailrec def count(value: Int, remaining: Seq[String]): Int = {
remaining match {
case head :: tail if head.length == 4 => count(value + 1, tail)
case head :: tail => count(value, tail)
case Nil => value
}
}
count(0, list)
}
이렇게 count 를 var 없이 구현 할 수 있습니다. 꼬리재귀라는것을 사용한것인데요
순수함수형 언어에서는 재귀를 주로 사용한다네요. 공재귀로 분해해보는 연습을 해야 합니다. 이거보고 스칼라는 쓸 때없이 복잡한거네라고 생각하지마시구요 여기서는 그냥 이런게 있구나 하고 지나치시고 나중에 다시 차근차근 쉽게쉽게 살펴보자구요. 분명히 먼가 좋으니깐 저렇게 쓰는거다라고 생각하시고 넘어갑시다.
마지막
List 의 짜증나는 규칙을 하나 억지로 외워봅시다.
val a = 1 :: 2 :: 3 :: Nil
는 List(1,2,3) 을 만들게 됩니다.
저 Nil 은 뭘까요?
리스트 끝에 Nil 이 필요로 하는 이유는 :: 메소드가 List 클래스의 멤버이기 때문이랍니다.
만약 1 :: 2 :: 3 만 사용했다고 치면 , 마지막의 3 이 Int 형이라서 :: 메소드가 없기때문에
그냥 꽝이 되버리는 반면
마지막에 Nil 을 넣어주게되면 Nil 은 List 의 멤버이기때문에 타입을 추론해서 List 로 만들어 줍니다.
스칼라 강좌 (6) - Map (0) | 2016.06.20 |
---|---|
스칼라 강좌 (5) - Set (0) | 2016.06.19 |
스칼라 강좌 (4) - Tuple (0) | 2016.06.19 |
스칼라 강좌 (2) - Array (0) | 2016.06.13 |
스칼라 강좌 (1 ) - 소개 (0) | 2016.06.13 |