Scala 스터디 3

young·2021년 9월 26일
0

싱글톤 객체

  • object로 싱글톤 객체 생성
  • 싱글톤 객체는 직접적으로 접근해서 사용할 수도 있고, import 선언으로 이용 가능
  • 싱글톤 객체의 메서드는 전역적으로 접근하고 참조할 수 있음
scala> object Bread {
	| 	val name: String = "기본빵"
	|	def cooking() = println("빵 만드는 중...")
	| }
scala> import Bread.cooking 	// import 
scala> cooking
빵 만드는 중...
scala> Bread.cooking
빵 만드는 중...

Companions

  • 싱글톤 객체와 클래스가 같은 이름을 사용하면 컴패니언이라고 함
  • 컴패니언은 정적 메소드의 보관 장소를 제공하므로, 자바의 satic 정적 데이터는 스칼라에서 컴패니언을 이용하면 됨
  • 컴패니언을 이용해 팩토리 메소드 같은 정적 메소드 작성
scala> :paste	// companions은 class와 object가 동시에 선언되어야 하므로 paste mode로 입력 
class Email(val username: String, val domainName: String)
object Email {
	def fromString(emailString:String): Option[Email] = {
		emailString.split('@') match {
			case Array(a, b) => Some(new Email(a, b))
			case _ => None 
		}
	}
}
scala> :paste
var scalaCenterEmail = Email.fromString("scala.center@epfl.ch") scalaCenterEmail match {
	case Some(email) => println( 
		s"""Registered an Email
		| Username: ${email.username}
		| Domain name: ${email.domainName}
		""")
	case None => println("Error: could not parse email")
}
scala>
Registered an Email 
Username: scala.center 
Domain name: epfl.ch

콜렉션 기본 자료 구조

1) Array

  • 길이가 고정된 자료구조
scala> val array1 = Array(1, 2, 3)
scala> array1(0)	// 배열 데이터 접근 res0: Int = 1
scala> array1(1) = 10	// 배열 데이터 변경 
scala> array1(1)
res1: Int = 10
scala> val array2 = Array(3, 4, 5)
scala> val array2 = array1 ++ array2	// 배열 연결하기 ++ 
scala> val array4 = 0 +: array3	// 배열 앞에 데이터 추가 
scala> val array5 = array3 :+ 100	// 배열 뒤에 데이터 추가

2) List

  • 가변적인 길이의 데이터를 저장하기 위한 자료구조
scala> val list1 = List(10, 20, 30, 40) 
scala> val list2 = (1 to 100).toList 
scala> val list3 = array1.toList

scala> list1
List[Int] = List(10, 20, 30, 40) 
scala> list1(2)
Int = 30
scala> list1.head
Int = 10
scala> list1.tail
List[Int] = List(20, 30, 40)

3) Set

  • 중복을 허용하지 않는 자료구조 전달된 값이 존재하는지 여부를 반환
scala> val s1 = Set(1, 1, 2)
scala> s1
scala.collection.immutable.Set[Int] = Set(1, 2)

// 전달된 값의 존재 여부 반환 scala> s1(1)
Boolean = true
scala> s1(2)
Boolean = true 
scala> s1(3) 
Boolean = false

4) Tuple

  • 불변의 데이터를 저장하는 자료구조
  • 여러가지 값을 저장할 수 있음, 패턴매칭에 이용할 수 있음
  • 값에 접근할 때는 _1, _2와 같은 형태로 접근
scala> val hostPort = ("localhost", 80)	// 튜플 
scala> hostPost._1
String = localhost

// 패턴매칭
scala> def matchTest(hostPort: (String, Int)) = hostPort match { 
	|	case ("localhost", port) => println(s"localhost, $port") 
	|	case (host, port) => println(s"$host, $port")
	| }
scala> val hostPort1 = ("localhost", 80) 
scala> val hostPort2 = ("localhost", 8080) 
scala> val hostPort3 = ("127.0.0.1", 8080) 
scala> matchTest(hortPort1)
localhost, 80
scala> matchTest(hortPort2) 
localhost, 8080
scala> matchTest(hortPort3) 
127.0.0.1, 8080

5) Map

  • 사전 형식으로 데이터를 저장하는 구조
  • 맵의 데이터를 반환하면 Option 타입으로 반환
scala> val map1 = Map(1 -> 2) 
scala> val map2 = Map("foo" -> "bar")

// Option 타입으로 반환 
scala> map1.get(1) Option[Int] = Some(2)
// getOrElse를 이용하여 키와 일치하는 데이터가 없으면 기본값을 반환하도록 설정 
scala> map1.getOrElse(1, 0)
Int = 2
scala> map1.getOrElse(10, 0)
Int = 0

반복문

1) for문

  • to는 이하의 리스트 생성, until은 미만의 시퀀스 생성
scala> for (num <- 0 to 3)	// 0에서 3이하의 시퀀스 | println(num)
0
1
2
3
scala> for (num <- 0 until 3)	// 0에서 3미만의 시퀀스
	|	println(num)
0
1 
2

scala> val strs = Array("A", "B", "C", "D", "E")
scala> for (index <- 0 until str.length)	// 배열 길이만큼 인덱스 호출
	| 	println(index, strs(index)) 
(0,A)
(1,B)
(2,C)
(3,D)
(4,E)
scala> for ((value, index) <- strs.zipWithIndex)	// zipWithIndex를 이용해 인덱스 호출
	| 	println(value, index)
(A,0)
(B,1) 
(C,2) 
(D,3) 
(E,4)

scala> val map = Map("k1"->"v1", "k2"->"v2", "k3"->"v3") s
cala> for ((k, v) <- map)	// 맵의 키,밸류는 튜플로 전달
	| 	println(k, v) 
(k2, v2)
(k1, v1) 
(k3, v3)

scala> for (x <- 0 to 2; y <- 0 to 2; if x < 1; if y < 1)	// 세미콜론으로 이중 for, 조건식 추가 
	| 	println(x, y)
(0, 0)
  • for문의 끝에 yield를 이용해 for문에서 생성한 값들의 시퀀스 반환
scala> def fives(n: Int) = {
	| 	for(x <- 0 to n; if x % 5 == 0)
	| 		yield x
	| }
scala> for (num <- fives(20))
	| 	println(num)
0 
5 
10 
15 
20

// 0 에서 num 미만의 숫자로 이루어진 조합에서 합이 sum인 값의 조합 찾는 함수 
scala> def checkSum(num: Int, sum: Int) =
	| 	for(start <- 0 until num; inner <- start until num; if start + inner == sum)
	| 		yield (start, inner);	// IndexedSeq 반환     
scala> checkSum(20, 32) foreach {
	| 	case (i, j) => println(s"($i, $j)")
	| } 
(13, 19) 
(14, 18) 
(15, 17) 
(16, 16)

2) while문

  • 조건이 true일 동안 반복
scala> var i = 0 
scala> do {
	|	println(i)
	|	i += 1 
	| } while(i < 3)
0
1
2

scala> var num = 0 
scala> while (num < 3) {
	|	num += 1 
	|	println(num)
	} 
0 
1 
2

콜렉션 함수

1) map

  • 각 아이템에 대해 동일한 작업 진행
scala> var list = (1 to 10)
scala> list.map(_+1)
Vector(2, 3, 4, 5, 6, 7, 8, 9, 10, 11)

scala> var strs = List("david", "kevin", "james") 
scala> strs.map(_.toUpperCase)
List("DAVID", "KEVIN", "JAMES")

2) reduce, fold

  • 데이터 집계 시 사용
  • 각 함수 모두 L/R 방향 가질 수 있어, 연산별로 방향에 따라 다른 결과 나타냄
  • fold() 함수는 기본 값 제공함
scala> var list = (1 to 10)
scala> list.reduce(_+_)	// 55 
scala> list.reduceLeft(_+_)	// 55 
scala> list.reduce(_-_)	// -53 
scala> list.reduceRight(_-_)	// -5 
scala> list.fold(10)(_+_)	// 65

3) groupBy

  • key 기준으로 데이터 병합
  • 결과를 Map 형식으로 반환하고 전달된 key와 list 형태의 데이터로 반환
scala> var datas = List(("A", 1), ("B", 2), ("C", 6), ("B", 2), ("A", 8), ("C", 2))

// List내 1번째 param의 데이터를 키로 잡고 이를 기준으로 병합
scala> datas.groupBy(_._1).foreach({ case (k, v) => printf("key: %s, value: %s\n", k, v) }) 
key: A, value: List((A, 1), (A, 8))
key: C, value: List((C, 6), (C, 2))
key: B, value: List((B, 2), (B, 2))

4) filter

// filter: 콜렉션 데이터를 필터링해 없애거나 분류 scala> var list = (1 to 10)
scala> list.filter(_ > 5)	// 5 이상의 데이터 분류 
Vector(6, 7, 8, 9, 10)

// partition: 콜렉션 분류
scala> list.partition(_%3 == 0)	// 2로 나누어 나머지가 0인 데이터 분류 
(Vector(3, 6, 9), Vector(1, 2, 4, 5, 7, 8, 10))

// find: 데이터 검색
scala> list.find(_ == 3)	// 3 검색 
Option[Int] = Some(3)

// takeWhile, dropWhile: 원하는 부분까지 데이터 선택 
scala> var list2 = List(1, 2, 3, -1, 4)
scala> list2.takeWhile(_ > 0)
List(1, 2, 3)
scala> list.dropWhile(_ < 3) 
List(3, -1, 4)

5) zip

  • 두 개의 콜렉션의 같은 인덱스를 묶을 수 있음
  • 길이가 일치하지 않으면 작은 개수 만큼만 반환
scala> for (item <- List(1, 2, 3).zip(List(1, 2, 3))) 
	|	println(item)
(1, 1)
(2, 2)
(3, 3)
scala> for (item <- List(1, 2, 3).zip(List(1, 2, 3, 4)))
	| 	println(item) 
(1, 1)
(2, 2) 
(3, 3)

6) mapValues

  • Map 타입의 데이터에서 value만 map 함수 처리하고 싶을 때 사용
scala> var maps = Map("A" -> 1, "B" -> 2, "C" -> 3, "D" -> 4, "E" -> 5)
scala> maps.mapValues(x => x*x).foreach(x => x match { case (k, v) => printf("key: %s, value: %s\n", k, v) })	// value 제곱
key: E, value: 25
key: A, value: 1
key: B, value: 4
key: C, value: 9
key: D, value: 16

scala> var maps = Map("A" -> List(1, 2, 3), "B" -> List(4, 5, 6), "C" -> List(7, 8, 9))
scala> maps.mapValues(_.sum).foreach({ case (k, v) => printf("key: %s, value: %s\n", k, v) })	// value sum
key: A, value: 6
key: B, value: 15
key: C, value: 24

7) sort

// sorted
scala> var list = List(4, 6, 1, 6, 0)
scala> val l_sort = list.sorted
scala> val r_sort = list.sorted(Ordering.Int.reverse) 
scala> println(l_sort)
List(0, 1, 4, 6, 6)
scala> println(r_sort)
List(6, 6, 4, 1, 0)

// sortBy
scala> val sList = List("aa", "bb", "cc")
scala> val l_sortBy = sList.sortBy(_.chatAt(0)) 
scala> println(l_sortBy)
List(aa, bb, cc)

// sortWith
scala> val l_sortWith = list.sortWith(_ <= _) 
scala> val r_sortWith = list.sortWith(_ >= _) 
scala> println(l_sortWith)
List(0, 1, 4, 6, 6)
scala> println(r_sortWith)
List(6, 6, 4, 1, 0)

// case class 데이터 정렬
// correct가 같으면 index로 정렬
scala> case class Person(idx: Int, var correct: Int)
scala> val persons = Array(Person(1, 3), Person(2, 4), Person(3, 4)) scala> val list = persons.sortWith((x: Person, y: Person) => {
	|	if(x.correct == y.corrent) 
	|		x.idx >= y.idx
	|	x.correct > y.correct
	| }).toList
scala> println(list)
List(Person(2, 4), Person(3, 4), Person(1, 3))

0개의 댓글