[Android] Collection 함수 알아보자

0
post-thumbnail

내가 공부하기 위해 모아놓은 Collection 함수 알아보자!

1. flatMap()

flatMap 함수는 단일 원소로 반환한다.

만약 List 안에 List가 담겨져있는 데이터가 있습니다.

이것을 만약 하나의 리스트로 바꾸고싶다면 어떻게 할수 있을까요?

Map 하나로는 불가능 합니다.

Map은 단일 요소(그 자체)를 리턴하기 때문이죠.

하지만 flatMap은 요소의 원소들을 리턴합니다.

2. distinct()

distinct는 MutableSet으로 변환후에, List로 다시 변환하여 반환한다.

public fun <T> Iterable<T>.distinct(): List<T> {
    return this.toMutableSet().toList()
}

이때 중복된 원소는 제거되며, 순서를 유지 시킵니다.

3. filter

filter는 말그대로 조건에 만족하는 원소들만 반환하는 함수 입니다.

//왠만한 자료구조에 필터라는 확장함수는 꼭 있다. 
public inline fun <T> Array<out T>.filter(predicate: (T) -> Boolean): List<T> {
    return filterTo(ArrayList<T>(), predicate)
}

중요한점은 안에 조건에 중위함수 in(contains로 이루어져있다.)을 사용할 수 있어서
리스트 두개를 만족하는 함수또한 filter를 통해 간단하게 구현할 수 있습니다.

val t = arrayOf("zero", "one", "two", "three", "four", "five" , "six", "seven", "eight" , "nine")
val n = arrayOf("0", "1", "2", "3", "4", "5" , "6", "7", "8" , "9")

// t에서 n이 둘다 같이 있는 함수가 나온다.
t.filter {it in n}

4. groupby()

5. Slice()

Slice()리스트의 일부분을 잘라 List로 받는 확장 함수입니다.

//지정된 indices 에 있는 요소를 포함하는 목록을 반환합니다.

public fun <T> List<T>.slice(indices: Iterable<Int>): List<T> {
    val size = indices.collectionSizeOrDefault(10)
    if (size == 0) return emptyList()
    val list = ArrayList<T>(size)
    for (index in indices) {
        list.add(get(index))
    }
    return list
}

지정된 사이즈의 List 객체를 새로 생성하고 거기에 add 시킵니다.

size가 미리 지정되어있고, 지정된 위치에 넣고 있지 않기 때문에 시간복잡도는 O(1)입니다.

6. Take()

Take()처음부터 지정된 인덱스까지 포함하는 리스트를 반환하는 확장 함수입니다.

/*
처음 n 요소를 포함하는 목록을 반환합니다.
던지기:
IllegalArgumentException - n 이 부의 경우
견본:
samples.collections.Collections.Transformations.tak
*/

public fun <T> Iterable<T>.take(n: Int): List<T> {
    require(n >= 0) { "Requested element count $n is less than zero." }
    
    if (n == 0) return emptyList()
    
    if (this is Collection<T>) {
    //n이 사이즈보다 클경우 다 들어있는 새로운 리스트 객체를 리턴 
        if (n >= size) return toList()
        if (n == 1) return listOf(first())
    }
    
    var count = 0
    val list = ArrayList<T>(n)
    // 정해진 n까지 하나하나씩 담는다.
    for (item in this) {
        list.add(item)
        if (++count == n)
            break
    }
    return list.optimizeReadOnlyList()
}

take() 또한 size가 미리 지정되어있고, 지정된 위치에 넣고 있지 않기 때문에 시간복잡도는 O(1)입니다.

7. Coerce 시리즈

public fun Double.coerceAtMost(maximumValue: Double): Double {
    return if (this > maximumValue) maximumValue else this
}

//사이값 확인할때
public fun <T : Comparable<T>> T.coerceIn(minimumValue: T?, maximumValue: T?): T {
    if (minimumValue !== null && maximumValue !== null) {
    //최소값이 최대값보다 클때 에러 반환
        if (minimumValue > maximumValue) throw IllegalArgumentException
        if (this < minimumValue) return minimumValue
        if (this > maximumValue) return maximumValue
    }
    else {
        if (minimumValue !== null && this < minimumValue) return minimumValue
        if (maximumValue !== null && this > maximumValue) return maximumValue
    }
    return this
}

Coerce강요하다는 의미로, 종종 해당 데이터가 내가 생각한범위를 벗어날때 그 크기를 제한해주는 함수입니다.

저는 이 함수를 애니메이션을 만들때, 너무 빨라지거나 느려지는 움직임을 보정하기위해 사용하곤 했습니다.

8. Zip()

/**
 * Returns a list of values built from the elements of `this` array and the [other] array with the same index
 * using the provided [transform] function applied to each pair of elements.
 * The returned list has length of the shortest array.
 * 
 * @sample samples.collections.Iterables.Operations.zipIterableWithTransform
 */
public inline fun <V> IntArray.zip(other: IntArray, transform: (a: Int, b: Int) -> V): List<V> {
	//두개의 파라미터에서 최소 사이즈를 구한다.
    val size = minOf(size, other.size)
    val list = ArrayList<V>(size)
    for (i in 0 until size) {
        list.add(transform(this[i], other[i]))
    }
    return list
}

보통 저희는 zip()을 압축하다는 의미로 많이 알고있는데 해당 함수도 두개의 배열을 합치는 역할을 합니다.
minOf()함수를 이용하기 때문에 서로 있는 인덱스까지만 가져옴을 알 수 있습니다.

profile
쉽게 가르칠수 있도록 노력하자

0개의 댓글