2013-10-06 10 views
15

에지도 Functional Programming Principles in Scala에서 컬렉션의 강의를 듣고, 나는이 예제를 보았다. 그러나지도를 만들 때 예상했던 것과 다른 결과를 얻었습니다.FlatMap 대 문자열

scala> s.map(c => ("." + c)) 
res8: scala.collection.immutable.IndexedSeq[String] = Vector(.H, .e, .l, .l, .o, 
                  ". ", .W, .o, .r, .l, 

나는 호출 위에, 문자열을 반환 내가 map -ing를 요하기 때문에, 즉 "순서"는 각 항목에 함수를 적용하고 새로운 "순서를."반환 할 것으로 예상

그러나, 나는 수행 할 수있는 map보다는 flatmapList[String] A의 :

scala> val sList = s.toList 
sList: List[Char] = List(H, e, l, l, o, , W, o, r, l, d) 

scala> sList.map(c => "." + c) 
res9: List[String] = List(.H, .e, .l, .l, .o, ". ", .W, .o, .r, .l, .d) 

왜 문자열에 map를 호출하는 IndexedSeq[String] 반환 형식이었다?

+2

> bag.flatMap(toInt).sum 

사용지도 방법을 사용하여 가방

val bag = List("1", "2", "three", "4", "one hundred seventy five") def toInt(in: String): Option[Int] = { try { Some(Integer.parseInt(in.trim)) } catch { case e: Exception => None } } 

에서 모든 정수를 추가하기 때문에 당신은 할 수 없습니다 하나의 Char 유형에 두 개의 문자를 넣으시겠습니까? 문자 + 문자는 문자열 유형을 생성하는 두 문자입니다. –

답변

23

이 동작의 이유는 "map"을 문자열에 적용하기 위해 스칼라가 문자열을 문자 시퀀스 (IndexedSeq[String])로 처리하기 때문입니다. 이것은 맵 호출의 결과로 얻는 것이며, 여기서 시퀀스의 각 요소에 대해 조작이 적용됩니다. 스칼라가 문자열을 map을 적용 할 시퀀스로 처리 했으므로 map이 반환합니다.

flatMap은 단순히 다시 문자열

+1

구현을 보지 않고'string' map이 그것을'IndexSeq [String]'으로 변환하고'flatten'이 그것을'String'으로 다시 변환하는 것을 보지 않고 어떻게 추측하는지 짐작할 수 있습니다. 그것은 scala의 일부 데이터 구조에'map' 또는'flatMap'을 적용 할 때마다 나에게 들려요 제가 시도해 보거나 구현을 보면 동작을 이해할 필요가 있습니다. 그렇다면 이것은 좋은 디자인 (명확한 코드 현명한)입니까? – Jas

7

지도 기능 c => ("." + c)에 그것을 "변환"는 문자를 받아 문자열을 반환, 나중에 그 순서에 flatten를 호출합니다. 그것은 List를 취하고 List of Lists를 반환하는 것과 같습니다. 플랫 맵은 그 뒤를 평평하게합니다.

문자열 대신 문자를 반환하면 결과가 병합되지 않아도됩니다 (예 : "abc".map(c => (c + 1).toChar)은 "bcd"를 반환합니다.

1

map을 사용하면 문자 목록을 가져 와서 문자열 목록으로 변환 할 수 있습니다. 그것이 결과입니다. map은 목록 길이를 절대로 변경하지 않습니다. 문자열 목록에는 원래 문자열에 문자가있는만큼 많은 요소가 있습니다.

flatMap으로 문자 목록을 가져 와서 문자열 목록으로 바꾸고 문자열을 한 문자열로 다시 채우십시오. flatMap은 목록의 한 요소를 여러 요소로 바꾸고 싶을 때 유용합니다. 물론 이것은 결과리스트가 0을 포함하여 어떤 길이라도 가질 수 있음을 의미합니다. 빈리스트에서 시작하지 않는 한 map으로는 불가능합니다.

7

흥미로운 "collection of Scala flatMap examples"

scala> val fruits = Seq("apple", "banana", "orange") 
fruits: Seq[java.lang.String] = List(apple, banana, orange) 

scala> fruits.map(_.toUpperCase) 
res0: Seq[java.lang.String] = List(APPLE, BANANA, ORANGE) 

scala> fruits.flatMap(_.toUpperCase) 
res1: Seq[Char] = List(A, P, P, L, E, B, A, N, A, N, A, O, R, A, N, G, E) 

상당히 차이, 오른쪽 : 이는 flatMapmap 사이의 차이를 도시?
StringChar의 시퀀스로 처리하므로 결과 문자열 목록을 일련의 문자 (Seq[Char])로 병합합니다.
flatMapmapflatten의 조합이므로 시퀀스에서 map을 먼저 실행 한 다음 flatten을 실행하면 표시된 결과가 나타납니다.

당신은지도를 실행하여이을 본 후 자신을 평평하게 할 수 있습니다

scala> val mapResult = fruits.map(_.toUpperCase) 
mapResult: Seq[String] = List(APPLE, BANANA, ORANGE) 

scala> val flattenResult = mapResult.flatten 
flattenResult: Seq[Char] = List(A, P, P, L, E, B, A, N, A, N, A, O, R, A, N, G, E) 
+0

안녕하세요 @VonC 나는 당신이 공유하는 링크에있는 예제를 찾으려고했습니다. 그의 블로그에 나와있는 예제와 같이 그는 아래의 예제에 대한 결과를 얻을 수 있지만 실행하려고 할 때'toInt' 함수를 적용하려고 할 때 String "foo"에 대한 Number Format Exception을 얻고 있습니다. 'scala> val 문자열 = Seq ("1", "2", "foo", "3", "bar")' '문자열 : Seq [java.lang.String] = 목록 (1, 2, foo , 3, bar)' 'scala> strings.map (toInt)' 'res0 : Seq [옵션 [Int]] =리스트 (일부 (1), 일부 (2), 없음, 일부 (3), 없음)' 'scala> strings.flatMap (toInt)' 'res1 : Seq [Int] = List (1, 2, 3)' – Explorer

+0

@Novice 재미있다. 그것은 다른 사람들이 그것을 시험해보기위한 자체 질문으로서 가장 좋을 것입니다. – VonC

+0

'flatMap은 String을 Char의 시퀀스로 취급하기 때문에 어떻게 추측 할 수 있습니까? 그것을 밖으로 시도해서? 그것의 구현을 보면서? – Jas

0

사용 flatMap 당신이 flattern 다음 지도을 실행 상황에서. 구체적인 상황은 이것이다 :

당신은 기존의 컬렉션 새 컬렉션을 만들 지도 (또는 에 대한/수율 표현)를 사용하는 •.

• 결과 집합은 목록 목록입니다.

당신은 전화 • 평평 즉시 지도 (또는 에 대한/수율 표현) 후.

이 상황이 발생하면 대신 flatMap을 사용할 수 있습니다.

예하십시오 flatMap 방법을 (필요한 3 단계)

bag.map(toInt) // List[Option[Int]] = List(Some(1), Some(2), None, Some(4), None) 

bag.map(toInt).flatten //List[Int] = List(1, 2, 4) 

bag.map(toInt).flatten.sum //Int = 7