본문 바로가기
language/Scala

[Scala] 스칼라 배우기 7. 스칼라 기본 문법6(반복문, 정렬, 그룹핑, 필터링)

by 스파이디웹 2023. 6. 11.
728x90

반복문

for

to는 이하의 리스트를 생성하고, until은 미만의 시퀀스를 생성

// 0에서 3이하의 시퀀스 
for (num <- 0 to 3)
    println(num)
0
1
2
3

// 0에서 3미만의 시퀀스 
for (num <- 0 until 3)
    println(num)
0
1
2

// 콜렉션의 데이터 출력 
val strs = Array("A", "B", "C", "D", "E")
for (str <- strs)
    println(str)
A
B
C
D
E

인덱스와 함께 처리

// 콜렉션의 데이터를 인덱스와 함께 출력 
for(index <- 0 until strs.length)
    println(index, strs(index))
(0,A)
(1,B)
(2,C)
(3,D)
(4,E)

// 콜렉션의 데이터를 zipWithIndex를 이용하여 인덱스와 함께 출력 
for((value, index) <- strs.zipWithIndex)
    println(value, index)
(A,0)
(B,1)
(C,2)
(D,3)
(E,4)

map의 key value 처리

// 맵 데이터 출력 
val map = Map("k1" -> "v1", "k2" -> "v2", "k3" -> "v3", "k4" -> "v4", "k5" -> "v5")
for ((k, v) <- map)
  println(k, v)

(k2,v2)
(k5,v5)
(k1,v1)
(k4,v4)
(k3,v3)

중첩 for문

중첩 for문은 자바처럼 for문을 두개를 이용해서 생성할 수도 있지만, 세미 콜론(;)을 이용하여 생성할 수도 있음

for (x <- 0 to 2; y <- 0 to 2)
    println(x, y)

(0,0)
(0,1)
(0,2)
(1,0)
(1,1)
(1,2)
(2,0)
(2,1)
(2,2)

조건식 추가

  • for문에 데이터 생성을 위한 조건식을 이용
  • 세미콜론으로 if문을 분할하여 여러개의 조건을 추가할 수 있음
for (num <- 0 to 3; if num != 2)
    println(num)
0
1
3

for (x <- 0 to 2; y <- 0 to 2; if x < 1)
    println(x, y)
(0,0)
(0,1)
(0,2)

for (x <- 0 to 2; y <- 0 to 2; if x < 1; if y < 1)
    println(x, y)
(0,0)

yield 이용한 시퀀스 컴프리헨션

시퀀스 컴프리헨션은 for문의 끝에 yield를 이용해서 for문에서 생성한 값들의 시퀀스를 반환

// 0에서 n이하의 시퀀스에서 5의 배수로 구성된 시퀀스 생성 
def fives(n: Int) = {
    for( x <- 0 to n; if x % 5 == 0)
      yield x
}

for(num <- fives(100))
    println(num)

0
5
10
15
20
25
30
35
40
45
50
55
60
65
70
75
80
85
90
95
100

do while

조건이 참일 동안만 반복하며 최초 한번은 무조건 수행

var i = 0;

do{
    println(i)
    i += 1
} while( i < 3)

0
1
2

while

조건이 참일 동안만 반복

  var num = 0;
  while (num < 3) {
    num += 1
    println(num);    
  }

1
2
3

map

콜렉션의 각 아이템에 대해서 동일한 작업을 해야할 때 사용

// 각 값에 1 추가 
val list = (1 to 10)
list.map(_ + 1)
// 결과 
Vector(2, 3, 4, 5, 6, 7, 8, 9, 10, 11)

// 각 문자를 대문자화 
val strs = List("david", "kevin", "james")
strs.map(_.toUpperCase)
// 결과 
List(DAVID, KEVIN, JAMES)

reduce,fold

  • reduce, fold 함수는 콜렉션의 데이터를 집계할 때 사용
  •  fold 함수는 기본값을 제공할 수 있음
  • 각각의 함수모두 left, right 방향을 가질 수 있음
  • 더하기(+) 연산의 경우 양쪽 방향이 동일한 결과를 나타내지만 빼기(-) 연산의 경우 방향에 따라 다른 결과를 나타냄
val list = (1 to 10)

list.reduce(_ + _)      // 55
list.reduceLeft(_ + _)      // 55
list.reduceRight(_ + _)     // 55

list.reduce(_ - _)      // -53
list.reduceLeft(_ - _)      // -53
list.reduceRight(_ - _)     // -5

list.fold(10)(_ + _)        // 65

그룹핑

groupBy

  • groupBy는 데이터를 키를 기준으로 병합할 때 사용
  • 결과를 Map 형식으로 반환하고, 전달된 키와 리스트 형태의 데이터로 반환
var datas = List(("A", 1), ("B", 2), ("C", 6), ("B", 2), ("A", 8), ("C", 2))
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))

필터링

filter

  • filter는 콜렉션의 데이터를 필터링하여 없애거나 분류할 때 사용할 수 있음
  • partition은 콜렉션을 분류할 때 사용
  • find는 데이터를 검색할 때 사용
  • takeWhile과 dropWhile을 이용하여 원하는 부분까지 데이터를 선택할 수 있음
val list = (1 to 10)
list.filter(_ > 5)  // 5 이상의 데이터 분류 
// 결과: Vector(6, 7, 8, 9, 10)

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

list.find(_ == 3)   // 3을 검색 
// 결과: Some(3)

val list2 = List(1, 2, 3, -1, 4, 5, 6)
list2.takeWhile(_ > 0)
// 결과: List(1, 2, 3)

val list3 = List(1, 2, 3, 4, 5, 6)
list3.dropWhile(_ < 2)
// 결과: List(2, 3, 4, 5, 6)

zip

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

for( item <- List(1,2,3).zip(List(1,2,3,4)))
      println(item)
(1,1)
(2,2)
(3,3)

mapValues

mapValues는 Map 타입의 데이터에서 밸류만 map 함수 처리를 하고 싶을 때 사용하는 함수

// value를 제곱
var maps = Map("A" -> 1, "B" -> 2, "C" -> 3, "D" -> 4, "E" -> 5)
maps.mapValues(x => x*x).foreach( x => x match { case (k, v) => printf("key: %s, value: %s\n", k, v) })

// 결과
key: E, value: 25
key: A, value: 1
key: B, value: 4
key: C, value: 9
key: D, value: 16

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

// 결과 
key: A, value: 6
key: B, value: 15
key: C, value: 24

정렬

sort

정렬은 sorted, sortWith, sortBy 세가지 메소드를 이용

// sorted 사용방법 
val list = List( 4, 6, 1, 6, 0)
val l_sort = list.sorted
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 사용방법 
val sList = List("aa", "bb", "cc")
val l_sortBy = sList.sortBy(_.charAt(0))
scala> println(l_sortBy)
List(aa, bb, cc)

// sortWith 사용방법 
val l_sortWith = list.sortWith(_ <= _)
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)


// 케이스 클래스의 데이터를 정렬 
// correct가 같으면 index로 정렬 
case class Person(index:Int, var correct:Int)

val persons = Array(Person(1, 3),Person(2, 4), Person(3, 4))
val list = persons.sortWith((x:Person, y:Person) => {
  if(x.correct == y.correct)
      x.index >= y.index

    x.correct > y.correct
}).toList

scala> println(list)
List(Person(2,4), Person(3,4), Person(1,3))

 

출처:

https://wikidocs.net/31491

728x90

댓글