일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 플레이프레임워크
- 파이썬 머신러닝
- Hyperledger fabric gossip protocol
- 엔터프라이즈 블록체인
- 스칼라 동시성
- Actor
- 스위프트
- 파이썬 데이터분석
- 블록체인
- hyperledger fabric
- 스칼라 강좌
- CORDA
- 파이썬 강좌
- Akka
- 하이브리드앱
- Golang
- 주키퍼
- 그라파나
- Play2 로 웹 개발
- 하이퍼레저 패브릭
- akka 강좌
- 안드로이드 웹뷰
- play2 강좌
- Adapter 패턴
- play 강좌
- Play2
- 파이썬
- 이더리움
- 스칼라
- 파이썬 동시성
- Today
- Total
HAMA 블로그
스칼라 강좌 (20) - 고차함수들 (zip,map,flatmap등) 본문
List 활용
* List 는 스칼라에서 가장 많이 사용되는 데이터 구조일 겁니다.
* 스칼라의 리스트는 디폴트로 불변형입니다.
* 스칼라의 리스트 타입은 공변적입니다.
길이 구하기
val a = List (1,2,3)
a.length // 3
*배열과 달리 리스트의 length 는 비교적 비싼 연산입니다.
a.isEmpty 를 a.length == 0 으로 사용하지 마세요.
양 끝에 접근하기
val a = List ('a','b','c','d')
a.head // 'a' 처음
a.last // 'd' 마지막
a.tail // List('b', 'c','d') 처음 제외 나머지
a.init // List('a','b','c') 마지막 제외 나머지
리스트 뒤집기
val a = List ('a',b','c','d')
a.reverse // List ('d','c','b','a') * 주의할것은 새로운 리스트가 생긴다는 점이다. 리스트는 불변이니깐~
drop / take / splitAt
val a = List ('a',b','c','d')
a.splitAt(2) // (List('a','b'), List('c','d'))
apply / indices
val a = List ('a',b','c','d')
a.apply(2) // 'c' * 배열에 비해 불리하다.
a.indices // Range (0,1,2,3) * 리스트에서 유효한 모든 인덱스의 리스트를 반환
flatten
val a = List ( List(1,2), List(3), List(4,5) )
a.flatten // List (1,2,3,4,5) * 리스트의 리스트일 경우에 한 해 하나로 반듯하게 펼친다.
zip / zipWithIndex
val a = List (1,2,3)
val b = List('a','b','c')
a.zip(b) // List( (1,'a'), (2,'b') , (3,'c') ) * 두 리스트를 순서쌍으로 묶는다.
b.zipWidhIndex // List ( ('a',0), ('b',2), ('c', 3) ) * 리스트의 원소를 인덱스와 함께 순서쌍으로 묶는다.
toString / mkString
val a = List ('a','b','c','d')
toArray / copyToArray
val a = List ('a','b','c','d')
val arr = a.toArray // Array(a,b,c,d) * array로 변환
arr.toList // List (a,b,c,d) * List 로 변환
List 클래스의 고차 메소드
map
val a = List (1,2, 3)
a.map(_ + 1) // List (2,3,4)
flatMap
val words = List ( "the" , "quick" , "brown" , "fox" )
words.map(_.toList) // List (List (t,h,e) , List (q,u,i, .........
words.flatMap(_.toList) // List (t,h,e,q,u,i ...........
map 과 flatMap의 차이
scala> val fruits = Seq("apple", "banana", "orange") fruits: Seq[java.lang.String] = List(apple, banana, orange) scala> fruits.map(_.toUpperCase) res0: Seq[java.lang.String] = List(APPLE, BANANA, ORANGE) scala> fruits.flatMap(_.toUpperCase) res1: Seq[Char] = List(A, P, P, L, E, B, A, N, A, N, A, O, R, A, N, G, E)
map 과 flatMap의 차이2 (이 특성은 너무너무너무 중요하다. 별표3개)
def toInt(s: String): Option[Int] = { try { Some(Integer.parseInt(s.trim)) } catch { // catch Exception to catch null 's' case e: Exception => None } }
scala> val strings = Seq("1", "2", "foo", "3", "bar") strings: Seq[java.lang.String] = List(1, 2, foo, 3, bar) scala> strings.map(toInt) res0: Seq[Option[Int]] = List(Some(1), Some(2), None, Some(3), None) scala> strings.flatMap(toInt) res1: Seq[Int] = List(1, 2, 3) scala> strings.flatMap(toInt).sum res2: Int = 6
map 은 타입을 감싼 타입을 그대로 내보내기 때문에 None 도 내보내지지만, flatMap 은 감싼 타입을 벗겨내기 때문에 None은 없어진다. 이 중요한 특성을 이용해서 예러(예외)가 없는 결과값을 연속적으로(함수합성)으로 사용하는게 가능해진다.
flatMap의 추가 특징1
scala> val map = Map(1 -> "one", 2 -> "two", 3 -> "three") map: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> one, 2 -> two, 3 -> three) scala> 1 to map.size flatMap(map.get) res0: scala.collection.immutable.IndexedSeq[java.lang.String] = Vector(one, two, three)
flatMap의 추가 특징2
flatMap 은 map 이랑 flatten 을 합해놓것과 같다. 예를들어 List[List[Int]] 를 List[Int] 로 바꿀려면 밑에 처럼 flatten 을 쓰면 된다.
그렇다면 List[List[Int]] 를 List[String] 으로 바꿀려면 어떻해야 할까? flatMap 을 쓰면된다.
flatMap은 모나드 이해라든지 함수형에서 매우 중요하므로 아래 2개의 글도 읽어볼것
foreach
val n = List ( 1,2,3,4 )
var sum = 0
n.foreach( sum += _) // sum 은 15 * 결과 자체는 Unit이다.
filter
val n = List ( 1,2,3,4 )
n.filter( _ % 2 == 0) // List (2,4) * 걸러서 버린다.
partition
val n = List ( 1,2,3,4 )
n.partition( _ % 2 == 0) // ( List (2,4) , List(1,3) ) * 걸러서 나눈다.
find
val n = List ( 1,2,3,4 )
n.find( _ % 2 == 0) // Some(2) * 만족하는 첫번째 원소 반환한다
sortWith
val n = List ( 1,-3,4,2,6 )
n.sortWith ( _ < _ ) // List (-3,1,2,4,5) *원소를 정렬한다
Reducing / Folding / Scanning
맵이 요소들에 어떤 변화를 가하여 전체 요소들을 개별적으로 바꾸어 주는 역할이라면
이것은 어떤 요소롤 가득찬 자료구조의 합쳐서 (더하거나 빼거나 등등) 단일 결과를 얻고 싶을때 사용한다.
reduceLeft
List(1,7,2,9).reduceLeft (_ - _)
는 ((1 - 7 ) - 2 ) - 9 = -17 이다.
(_ - _) 여기의 왼쪽 _ 이 누적값이고 오른쪽 _ 은 각 요소들이다.
reduceRight
(_ - _) 여기의 오른쪽 _ 이 누적값이고 왼쪽 _ 은 각 요소들이다.
foldLeft
val numbers = List(1,7,2,9)
scala> numbers.foldLeft(0)((m: Int, n: Int) => m + n) res0: Int = 19
0은 시작 값이고 m은 값을 누적하는 변수 역할을 한다. n 은 물론 리스트의 요소이다.
0 + 1 + 7 + 2 + 9 이고
(0 /: List(1,7,2,9)) (_+_) 이렇게 쓸 수도 있다.
사실 이런 예제라면 그냥 sum 을 사용하면 된다.
'Scala' 카테고리의 다른 글
스칼라 강좌 (22) - apply 정리 (0) | 2016.09.30 |
---|---|
스칼라 강좌 (21) - Option 과 Either (0) | 2016.09.29 |
스칼라 강좌 (19) - implicit (0) | 2016.08.13 |
스칼라 강좌 (18) -trait (1) | 2016.08.06 |
스칼라 강좌 (17) - case class (0) | 2016.08.06 |