Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package com.example.learningtest.collection.functional

import io.kotest.core.spec.style.FreeSpec
import io.kotest.matchers.shouldBe

class FilteringTest : FreeSpec({
"List Filter Api" - {
"filter - 쑰건을 λ§Œμ‘±ν•˜λŠ” κ²ƒλ§Œ 남기기" {
val numbers: List<Int> = listOf(1, 2, 3, 4, 5, 6)
numbers.filter { it % 2 == 0 } shouldBe listOf<Int>(2, 4, 6)
}

"filterNot - 쑰건을 λ§Œμ‘±ν•˜μ§€ μ•ŠλŠ” μš”μ†Œλ§Œ 남기기" {
val words: List<String> = listOf("a", "be", "cat")
words.filterNot { it.length > 1 } shouldBe listOf<String>("a")
}

"filterIndexed - μΈλ±μŠ€μ™€ ν•¨κ»˜ 필터링" {
val words: List<String> = listOf("zero", "one", "two", "three")
val result = words.filterIndexed { index, _ -> index % 2 == 0 }
result shouldBe listOf<String>("zero", "two")
}

"take - μ•žμ—μ„œλΆ€ν„° N개 κ°€μ Έμ˜€κΈ°" {
val numbers: List<Int> = listOf(0, 1, 2, 3, 4)
numbers.take(2) shouldBe listOf<Int>(0, 1)
}

"drop - μ•žμ—μ„œλΆ€ν„° N 개 버리고 λ‚˜λ¨Έμ§€ κ°€μ Έμ˜€κΈ°" {
val numbers: List<Int> = listOf(0, 1, 2, 3, 4)
numbers.drop(2) shouldBe listOf<Int>(2, 3, 4)
}

"takeWhile - μ•žμ—μ„œλΆ€ν„° 쑰건이 거짓이기 μ „κΉŒμ§€ κ°€μ Έμ˜€κΈ°(κ±°μ§“μ΄λ˜λ©΄ 순회 쀑지)" {
val numbers: List<Int> = listOf(1, 2, 3, 0, 4)
numbers.takeWhile { number -> number > 0 } shouldBe listOf<Int>(1, 2, 3)
}

"dropWhile - μ•žμ—μ„œλΆ€ν„° 쑰건이 참이기 μ „κΉŒμ§€ 버리고 λ‚˜λ¨Έμ§€ κ°€μ Έμ˜€κΈ°(참이 되면 순회 쀑지)" {
val numbers: List<Int> = listOf(1, 2, 3, 0, 4)
numbers.dropWhile { it > 0 } shouldBe listOf<Int>(0, 4)
}

"filterTo - 필터링 κ²°κ³Όλ₯Ό κΈ°μ‘΄ μ»¬λ ‰μ…˜μ— μΆ”κ°€" {
val target: MutableList<Int> = mutableListOf(0, 9)
val source: List<Int> = listOf(1, 2, 3, 4)
source.filterTo(target) { it > 2 }

target shouldBe listOf<Int>(0, 9, 3, 4)
}

"filterIndexedTo - μΈλ±μŠ€μ™€ ν•¨κ»˜ 필터링 κ²°κ³Όλ₯Ό κΈ°μ‘΄ μ»¬λ ‰μ…˜μ— μΆ”κ°€" {
val target: MutableList<String> = mutableListOf("hello", "world")
val source: List<String> = listOf("a", "b", "c", "d")
source.filterIndexedTo(target) { index, _ -> index % 2 == 0 }

target shouldBe listOf<String>("hello", "world", "a", "c")
}

"filterNotTo - 쑰건을 λ§Œμ‘±ν•˜μ§€ μ•Šμ€ κ²ƒλ§Œ ν•„ν„°λ§ν•΄μ„œ κΈ°μ‘΄ μ»¬λ ‰μ…˜μ— μΆ”κ°€" {
val target: MutableList<Int> = mutableListOf(3, 3)
val source: List<Int> = listOf(1, 2, 3, 4)
source.filterNotTo(target) { it % 2 == 0 }

target shouldBe listOf<Int>(3, 3, 1, 3)
}

"filterIsInstance - νƒ€μž… 필터링" {
val list: List<Any> = listOf(1, "a", 2L, 'b', "c")
list.filterIsInstance<String>() shouldBe listOf("a", "c")
}

"filterIsInstanceTo - νƒ€μž… 필터링 ν›„ λ‹€λ₯Έ μ»¬λ ‰μ…˜μ— μ €μž₯" {
val target: MutableList<String> = mutableListOf("d")
val source: List<Any> = listOf("a", 1, 'b', 2L, "c")

source.filterIsInstanceTo(target) shouldBe listOf<String>("d", "a", "c")
}

"distinct - 쀑볡 제거" {
val list: List<Int> = listOf(1, 2, 3, 1, 2)
list.distinct() shouldBe listOf<Int>(1, 2, 3)
}

"distinctBy - 쑰건에 따라 쀑볡 제거 (λŒ€ν‘œ μš”μ†Œ ν•˜λ‚˜λ§Œ 남김)" {
val list: List<String> = listOf("aaa", "bbb", "ccc", "aa", "bb", "cc", "a", "b", "c")
list.distinctBy { it.length } shouldBe listOf<String>("aaa", "aa", "a")
}

"partition - 쑰건에 따라 두 그룹으둜 λ‚˜λˆ„κΈ°" {
val list: List<Int> = listOf(1, 2, 3, 4, 5)
val (even: List<Int>, odd: List<Int>) = list.partition { it % 2 == 0 }

even shouldBe listOf(2, 4)
odd shouldBe listOf(1, 3, 5)
}
}

"Map Filter Api" - {
val map: Map<String, Int> =
mapOf(
"a" to 1,
"b" to 2,
"c" to 3,
"d" to 4,
)

"filter - (key, value) 쌍으둜 필터링" {
// requires a pair of parentheses around the key and value in the lambda block.
val result: Map<String, Int> =
map.filter { (key, value) -> key in listOf<String>("a", "c") && value % 2 == 1 }

result shouldBe mapOf<String, Int>("a" to 1, "c" to 3)
}

"filterKeys - key κΈ°μ€€ 필터링" {
val result: Map<String, Int> = map.filterKeys { it > "b" }
result shouldBe mapOf<String, Int>("c" to 3, "d" to 4)
}

"filterValues - value κΈ°μ€€ 필터링" {
val result: Map<String, Int> = map.filterValues { it % 2 == 0 }
result shouldBe mapOf<String, Int>("b" to 2, "d" to 4)
}

"filterNot - 쑰건을 λ§Œμ‘±ν•˜μ§€ μ•ŠλŠ” (key, value) 필터링" {
val result: Map<String, Int> = map.filterNot { (_, value) -> value > 2 }
result shouldBe mapOf("a" to 1, "b" to 2)
}

"filterTo - 쑰건을 λ§Œμ‘±ν•˜λŠ” ν•­λͺ©μ„ λ‹€λ₯Έ MutableMap에 μΆ”κ°€" {
val source: Map<String, Int> = mapOf("one" to 1, "two" to 2, "three" to 3)
val target: MutableMap<String, Int> = mutableMapOf()

source.filterTo(target) { (_, v) -> v % 2 == 1 }

target shouldBe mapOf("one" to 1, "three" to 3)
}

"filterNotTo - 쑰건을 λ§Œμ‘±ν•˜μ§€ μ•ŠλŠ” ν•­λͺ©μ„ target에 μΆ”κ°€" {
val source: Map<String, Int> = mapOf("a" to 1, "b" to 2, "c" to 3)
val result: MutableMap<String, Int> = mutableMapOf()

source.filterNotTo(result) { (_, v) -> v > 1 }

result shouldBe mapOf("a" to 1)
}
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package com.example.learningtest.collection.functional

import io.kotest.core.spec.style.FreeSpec
import io.kotest.matchers.shouldBe

class FlatteningTest : FreeSpec({
"List 의 flattening" - {
"flatten - μ€‘μ²©λœ 리슀트λ₯Ό 평탄화" {
val nested: List<List<Int>> =
listOf(
listOf(1, 2),
listOf(3, 4),
)

nested.flatten() shouldBe listOf(1, 2, 3, 4)
}

"flatten - 깊이 n 번의 쀑첩은 n 번의 flatten 으둜 평탄화" {
val nested: List<List<List<Int>>> =
listOf(
listOf(
listOf(1, 2),
listOf(11, 22),
),
listOf(
listOf(3, 4),
listOf(33, 44),
),
)

val onceFlattened: List<List<Int>> = nested.flatten()
val twiceFlattened: List<Int> = onceFlattened.flatten()

onceFlattened shouldBe
listOf(
listOf(1, 2),
listOf(11, 22),
listOf(3, 4),
listOf(33, 44),
)
twiceFlattened shouldBe listOf(1, 2, 11, 22, 3, 4, 33, 44)
}

"flatMap - 각 μš”μ†Œλ₯Ό μ—¬λŸ¬ 개둜 펼친 ν›„ 평탄화" {
val nested: List<List<Int>> =
listOf(
listOf(1, 2),
listOf(3, 4),
)

val flattened: List<Int> = nested.flatMap { it }
flattened shouldBe listOf(1, 2, 3, 4)
}

"flatMapIndexed - μΈλ±μŠ€μ™€ ν•¨κ»˜ 각 μš”μ†Œλ₯Ό μ—¬λŸ¬ 개둜 펼친 ν›„ 평탄화" {
val nested: List<List<Int>> =
listOf(
listOf(1, 2),
listOf(3, 4),
)

val flattened: List<Int> =
nested.flatMapIndexed { index, list ->
list.map { value -> index * value }
}

flattened shouldBe listOf(0, 0, 3, 4)
}

"flatMapTo - μ€‘μ²©λœ 리슀트λ₯Ό ν‰νƒ„ν™”ν•΄μ„œ κΈ°μ‘΄ μ»¬λ ‰μ…˜μ— μΆ”κ°€" {
val source: List<List<Int>> =
listOf(
listOf(1, 2),
listOf(3, 4),
)
val destination: MutableList<Int> = mutableListOf(0)
source.flatMapTo(destination) { it }

destination shouldBe listOf(0, 1, 2, 3, 4)
}

"flatMapIndexed - μΈλ±μŠ€μ™€ ν•¨κ»˜ 각 μš”μ†Œλ₯Ό μ—¬λŸ¬ 개둜 펼친 ν›„ ν‰νƒ„ν™”ν•΄μ„œ κΈ°μ‘΄ μ»¬λ ‰μ…˜μ— μΆ”κ°€" {
val nested: List<List<Int>> =
listOf(
listOf(1, 2),
listOf(3, 4),
)
val destination: MutableList<Int> = mutableListOf(0, 1, 2)
nested.flatMapIndexedTo(destination) { index, list ->
list.map { value -> value * 2 }
}

destination shouldBe listOf(0, 1, 2, 2, 4, 6, 8)
}
}

"Map 의 flattening" - {
"flatMap - Map<K, List<V>> ꡬ쑰λ₯Ό 평탄화" {
val map: Map<String, List<Int>> =
mapOf(
"a" to listOf(1, 2),
"b" to listOf(3),
)

val result: List<String> =
map.flatMap { (key, numbers) ->
numbers.map { number -> "$key:$number" }
}

result shouldBe listOf<String>("a:1", "a:2", "b:3")
}

"flatMap - 사싀 flatMap 의 λžŒλ‹€ νŒŒλΌλ―Έν„°μ˜ 리턴 νƒ€μž…μ΄ Iterable νƒ€μž…μ΄κΈ°λ§Œ ν•˜λ©΄ λœλ‹€." {
val map: Map<String, Int> =
mapOf(
"a" to 1,
"b" to 2,
"c" to 3,
)

val result: List<Int> =
map.flatMap { (_, number) ->
List(number) { number }
}

result shouldBe listOf<Int>(1, 2, 2, 3, 3, 3)
}

"toList - Map<K, V> λ₯Ό List<Pair<K, V>> 둜 λ³€ν™˜" {
val map: Map<String, List<Int>> =
mapOf(
"a" to listOf(1, 2),
"b" to listOf(3),
)

val toList: List<Pair<String, List<Int>>> = map.toList()

toList shouldBe
listOf<Pair<String, List<Int>>>(
"a" to listOf<Int>(1, 2),
"b" to listOf<Int>(3),
)
}

"flatMapValues λ©”μ„œλ“œλŠ” λ”°λ‘œ μ—†μ–΄μ„œ Map<K, V>.values.flatten μ‚¬μš©" {
val map: Map<String, List<Int>> =
mapOf(
"a" to listOf(1, 2),
"b" to listOf(3),
)

val result: List<Int> = map.values.flatten()
result shouldBe listOf<Int>(1, 2, 3)
}

"flatPairValues λ©”μ„œλ“œλŠ” λ”°λ‘œ μ—†μ–΄μ„œ μ•„λž˜μ²˜λŸΌ μž¬κ΅¬μ„± ν•„μš”" {
val map: Map<String, List<Int>> =
mapOf(
"a" to listOf(1, 2),
"b" to listOf(3),
)

val result1: List<Pair<String, Int>> =
map.flatMap { entry ->
entry.value.map { value -> entry.key to value }
}

val result2: List<Pair<String, Int>> =
map.entries.flatMap { entry ->
entry.value.map { value -> entry.key to value }
}

result1 shouldBe
listOf<Pair<String, Int>>(
"a" to 1,
"a" to 2,
"b" to 3,
)
result1 shouldBe result2
}

"Map<String, String>.toList(). 은 λ‹¨μˆœ List<Pair<Key, Value>> 리슀트둜 λ³€ν™˜" {
val map: Map<String, String> =
mapOf(
"a" to "1",
"b" to "2",
"c" to "3",
)

val flatList: List<Pair<String, String>> = map.toList()

flatList shouldBe
listOf<Pair<String, String>>(
"a" to "1",
"b" to "2",
"c" to "3",
)
}
}
})
Loading