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


130

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


2
감소 .
Zoe

4
한 번 봐 가지고 이 주제에 대한 깊은 근본적인 논의
GhostCat

2
@LunarWatcher, 나는 그 문서들을 보았지만 그것을 얻지 못했습니다. 질문을 게시했습니다.
TapanHP

1
@MattKlein 완료
Jayson Minard

답변:


280

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작업이 적용중인 컬렉션의 값 이외의 값에 의존하지 않는 경우에 사용할 수 있습니다 .


47
좋은 설명입니다! 또한 빈 컬렉션을 줄일 수는 없지만 접을 수 있다고 말합니다.
Miha_x64

Kotlin의 초급 수준에있는 m을 참조하십시오. 첫 번째 예는 몇 가지 단계와 최종 답변으로 더 자세히 설명 할 수 있습니까? 큰 도움이 될 것입니다
TapanHP

3
@TapanHP emptyList<Int>().reduce { acc, s -> acc + s }는 예외를 생성하지만 emptyList<Int>().fold(0) { acc, s -> acc + s }괜찮습니다.
Miha_x64

31
reduce는 람다의 리턴이리스트 멤버와 동일한 유형이되도록 강제합니다. 이것은 목록의 첫 번째 요소 인 누산기의 초기 값을 만드는 중요한 결과입니다.
andresp December

4
@andresp : 완성도를위한 참고 사항 : 같은 유형일 필요는 없습니다 . 리스트 멤버는 또한 누산기의 하위 유형이 될 수 있습니다. 이것은 작동합니다 listOf<Int>(1, 2).reduce { acc: Number, i: Int -> acc.toLong() + i }(어큐뮬레이터 유형은 숫자로 선언되고 실제로는 긴 동안리스트 유형은 Int입니다)
Boris

11

내가 부르는 주요 기능 차이 (다른 답변에 대한 의견에서 언급되었지만 이해하기 어려울 수 있음)는 빈 컬렉션에서 수행되면 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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.