리스트 변환 연산자 map 과 flatMap의 차이와 활용 방법에 대한 정리
(1) map : iterator()로 각 아이템 꺼내옴 -> 변형 -> 방출
(2) flatMap : iterator() 로 아이템 하나씩 꺼내옴 -> 새로운 리스트로 변형 -> 방출
map은 익히 알고 있는 for문과 동일하기 때문에 이해하기 쉬운데
flatMap은 문서만 보고선 도저히 이해하기 어렵다. ( 개념이 와닿지가 않는다. flat하게 만든다는게 무슨말이지? )
실 예로 flatMap 이해하기
1. 리스트 2배로 변형
fun main() {
val list = listOf(
Cat(1, "naong"),
Cat(2, "persian"),
Cat(3, "sham")
)
//고양이 2배로 증식하기
val new = list.flatMap{cat->
listOf(
Cat(cat.id, cat.name),
Cat(cat.id, cat.name)
)
}
println(new)
}
data class Cat (
val id: Int,
val name: String
)
// [Cat(id=1, name=naong), Cat(id=1, name=naong), Cat(id=2, name=persian),
// Cat(id=2, name=persian), Cat(id=3, name=sham), Cat(id=3, name=sham)]
( val new = list + list 와는 다른 결과 )
2. 리뷰 리스트를 조건에 맞게 변형 ( + sealed class )
- 헤더에는 리뷰추가 버튼이 들어간다 ( 0번 인덱스 )
- 본문에는 reply 존재유무에 따라 질문, 답변을 구분한다
data class Review(
val id:Int,
val content:String,
val reply:String?
)
//위의 리스트를 내가 원하는 ReviewUi의 형태로 변환
sealed class ReviewUi {
data class Header(
val id:Int
):ReviewUi()
data class Question(
val id:Int,
val content:String
):ReviewUi()
data class Reply(
val id:Int,
val reply:String
):ReviewUi()
}
fun main() {
val list = listOf(
Review(1,"내용","답변"),
Review(2,"내용22",null),
Review(3,"내용33","답변33")
)
/* 1. 첫번째 항목은 Header가 고정
2. list의 첫번째 항목과 세번째 항목은 reply가 있으므로 Question, Reply로 나눔
3. list의 두번째 항목은 reply가 null이므로 Question 만 있음 */
val new = listOf(
ReviewUi.Header(0)
) + list.flatMap{ review->
if(review.reply == null){
listOf(
ReviewUi.Question(review.id, review.content)
)
}else{
listOf(
ReviewUi.Question(review.id, review.content),
ReviewUi.Reply(review.id, review.reply)
)
}
}
print(new)
// [Header(id=0),
// Question(id=1, content=내용), Reply(id=1, reply=답변),
// Question(id=2, content=내용22),
// Question(id=3, content=내용33), Reply(id=3, reply=답변33)]
}
3. 채팅 리스트를 조건에 맞게 변형 ( + groupBy )
- 내가 보낸 메시지와 상대방이 보낸 메시지를 구분
- 날짜가 변경된 경우 각 메시지 사이에 날짜를 넣어줌
data class Chat(
val id:Int,
val userName:String,
val message:String,
val createdDate:String
)
// 위의 Chat 모델을 아래의 ChatUI형태로 변환
sealed class ChatUi{
data class Me(
val message:String,
val date:String
) : ChatUi()
data class You(
val message:String,
val date:String
) : ChatUi()
data class Date(
val date : String
) : ChatUi()
}
fun main() {
val list = listOf(
Chat(1, "You", "message1", "2020/04/01"),
Chat(2, "Me", "message2", "2020/04/01"),
Chat(3, "Me", "message3", "2020/04/02")
)
val new = list.groupBy{ chat ->
chat.createdDate
}.flatMap{ (createdDate,messages)->
listOf(
ChatUi.Date(createdDate),
) +
messages.map{ message ->
if(message.userName == "Me"){
listOf(ChatUi.Me(message.message,message.createdDate))
}else{
listOf(ChatUi.You(message.message,message.createdDate))
}
}
}
print(new)
//[Date(date=2020/04/01),
//[You(message=message1, date=2020/04/01)],
//[Me(message=message2, date=2020/04/01)],
// Date(date=2020/04/02),
//[Me(message=message3, date=2020/04/02)]]
}
지금까지 flatMap 의 활용법에 대해 알아보았습니다
- 추가 : flatMap 좀더 깊게 이해하기
val datas = listOf(
Student(
subscribedCourses = listOf(
Course(name = "Maths", isPaid = false),
Course(name = "Arts", isPaid = true)
)
),
Student(
subscribedCourses = listOf(
Course(name = "History", isPaid = true),
Course(name = "Biology", isPaid = true)
)
),
Student(
subscribedCourses = listOf(
Course(name = "Physics", isPaid = true),
Course(name = "History", isPaid = true)
)
)
)
위의 List<Student> 데이터를 flat하게 만들고 싶을때 -> Cource List로 만들기
datas.flatMap { student ->
student.subscribedCourses
}
-> [Course(name=Maths, isPaid=false), Course(name=Arts, isPaid=true),
Course(name=History, isPaid=true), Course(name=Biology, isPaid=true),
Course(name=Physics, isPaid=true), Course(name=History, isPaid=true)]
'Android' 카테고리의 다른 글
비동기 함수 - Rx로 변경하기 (0) | 2021.05.14 |
---|---|
웹뷰 스크롤 전파 (0) | 2021.04.03 |
Data class + DiffUtil 이슈 (0) | 2021.03.25 |
Jetpack Navigation Component 활용하기 (0) | 2020.11.22 |
Hilt 사용법 및 Module (Binds vs Provides) 정리 및 후기 (4) | 2020.11.15 |