[kotlin] Kotlin에서 접기와 축소의 기본 차이점은 무엇입니까? 언제 사용합니까?

나는이 두 기능 fold()과 꽤 혼란스럽고 reduce()Kotlin에서는 누구나이 둘을 구별하는 구체적인 예를 줄 수 있습니까?



답변

fold 는 초기 값을 취하며, 전달 된 람다의 첫 번째 호출은 해당 초기 값과 컬렉션의 첫 번째 요소를 매개 변수로받습니다.

예를 들어 정수 목록의 합계를 계산하는 다음 코드를 사용하십시오.

listOf(1, 2, 3).fold(0) { sum, element -> sum + element }

람다에 대한 첫 번째 호출은 매개 변수 01입니다.

초기 값을 전달할 수있는 기능은 작업에 일종의 기본값 또는 매개 변수를 제공해야하는 경우에 유용합니다. 예를 들어, 목록 내에서 최대 값을 찾고 있지만 어떤 이유로 적어도 10을 반환하려는 경우 다음을 수행 할 수 있습니다.

listOf(1, 6, 4).fold(10) { max, element ->
    if (element > max) element else max
}

reduce초기 값을 사용하지 않고 대신 컬렉션의 첫 번째 요소로 누적 기 ( sum다음 예제에서 호출 )로 시작합니다.

예를 들어, 정수를 다시합시다 :

listOf(1, 2, 3).reduce { sum, element -> sum + element }

여기서 람다에 대한 첫 번째 호출은 매개 변수 12입니다.

reduce작업이 적용중인 컬렉션의 값 이외의 값에 의존하지 않는 경우에 사용할 수 있습니다 .


답변

내가 부르는 주요 기능 차이 (다른 답변에 대한 의견에서 언급되었지만 이해하기 어려울 수 있음)는 빈 컬렉션에서 수행되면 reduce 예외가 발생 한다는 입니다.

listOf<Int>().reduce { x, y -> x + y }
// java.lang.UnsupportedOperationException: Empty collection can't be reduced.

.reduce“데이터 없음”의 경우 어떤 값을 반환할지 알 수 없기 때문 입니다.

이 값과 대조하십시오 .fold. 빈 컬렉션의 경우 기본값 인 “시작 값”을 제공해야합니다.

val result = listOf<Int>().fold(0) { x, y -> x + y }
assertEquals(0, result)

따라서 컬렉션을 다른 (관련되지 않은) 유형의 단일 요소로 집계하지 않으려는 경우에도 (만 .fold허용 할 수 있음) 시작 컬렉션이 비어 있으면 컬렉션을 확인해야합니다 먼저 크기를 정한 다음 .reduce사용하십시오..fold

val collection: List<Int> = // collection of unknown size

val result1 = if (collection.isEmpty()) 0
              else collection.reduce { x, y -> x + y }

val result2 = collection.fold(0) { x, y -> x + y }

assertEquals(result1, result2)


답변