최근에 현업 프로젝트에서 정렬을 하는 기능이 있어서, 구현 내용을 공유하고자 합니다.
서버에서 전체 목록을 받은 후, 이를 점수로 정렬한 후에, 같은 점수 내에서 이름순으로 정렬하는 기능입니다.
샘플 프로젝트로 재구성 해보았습니다.
1. 샘플 데이터 만들기
UserScore 라는 데이터 클래스를 만들고 이름과 점수를 입력 받습니다.
일반적인 서비스라면 서버에서 데이터를 받아야 하겠지만, 샘플 프로젝트이니, 더미 데이터를 전달할수 있는 fetchList() 함수를 만들었습니다.
data class UserScore (val name: String, val score: Int) {
companion object {
fun fetchList(): List<UserScore> {
return listOf(
UserScore("아이유", 64),
UserScore("사나", 31),
UserScore("Zivana", 87),
...
)
}
}
}
2. ViewModel 구현
fetchUserScoreList() 함수로 목록을 요청하게 됩니다.
그리고, UserScore.fetchList()로 더미 데이터를 가져오게 됩니다.
class SortedWithExampleViewModel : ViewModel() {
private val _userScores: MutableLiveData<List<UserScore>?> = MutableLiveData()
val userScores: LiveData<List<UserScore>?> get() = _userScores
fun fetchUserScoreList() {
viewModelScope.launch {
_userScores.postValue(
UserScore.fetchList()
.sortedWith(compareByDescending(UserScore::score)
.thenBy(UserScore::name)
// 추가 테스트 코드
// .sortedWith(compareBy { it.name.length }
// .thenComparator { data1, data2 ->
// OrderKoreaFirst.compare(data1.name, data2.name)
// }
)
)
}
}
}
이제 sortedWith() 를 이용하여 정렬을 합니다.
sortedWith() 는 list를 compare 값에 따라 정렬을 하고, thenBy()를 통해서 정렬된 결과에서 추가로 정렬을 이어서 할수 있습니다.
구현된 위의 코드에서 compareByDescending(UserScore::score)는 UserScore 데이터 클래스의 score 변수를 기준으로 높은 점수순으로 정렬을 하는 코드입니다.
이어서 .thenBy(UserScore::name) 는 앞서 정렬된 결과에서 같은 결과(동일 점수) 내에서 텍스트순(숫자 > 영문 > 한글)으로 졍렬을 합니다.
그리고, 정렬된 결과를 반환해주게 됩니다. (원본 리스트는 변경되지 않습니다.)
만약, 변수의 속성값으로 정렬을 해야 한다면, 주석으로 처리한 방법을 사용하시면 됩니다.
compareBy { it.name } , .thenBy { it.name.lenght } 등의 중괄호를 사용하여 구현합니다.
3. 이름 정렬 순서 변경 (한글 > 영문 > 숫자)
이름 정렬 순서를 한글이 우선으로 표시해 달라는 요청 사항이 있어, 수정을 진행합니다.
처음엔 .thenByDescending(UserScore::name) 로 수정하면 간단할거라 생각했는데,
한글 역순이라 'ㅎ' > 'ㅍ' > .... 순으로 표시가 되어, 이 방법은 사용할 수 없었습니다.
구글링을 하니, 맨 위에 딱~! 나옵니다.(한국 개발자라면 같은 이슈가 있나봅니다.ㅎㅎ)
[Kotlin] 문자열 배열 한글, 영문, 숫자로 정렬 시키기
우선 출처는, 영문 -> 특수문자 순으로 정렬을 합니다. 지난 번 프로젝트 하면서 동일한 요구사항이 있었는데, 생각보다 머리아프더라고요. 그냥 문자열순으로 정렬하면 그 순서가 " data-og-host="ww
tempodivalse.tistory.com
위의 블로그 글을 참고하여 개발했습니다.
.thenComparator { data1, data2 ->
OrderKoreaFirst.compare(data1.name, data2.name)
}
OrderKoreaFirst 클래스가 한글 > 영문 > 숫자 순으로 정렬을 해주는 클래스이고, compare()에 name을 각각 전달하여 순서를 정렬하게 됩니다.
(OrderKoreaFirst 클래스의 소스는 아래 전체 코드 링크를 확인해주세요.)
아래와 같이 만족스러운 결과가 나왔습니다.
전체 소스코드는 아래 Github 링크 확인해주세요.
GitHub - rcbuilders/RemindSampleApp: https://heeeju4lov.tistory.com/ 블로그에서 Android + Kotlin 강좌에서 사용함.
https://heeeju4lov.tistory.com/ 블로그에서 Android + Kotlin 강좌에서 사용함. - GitHub - rcbuilders/RemindSampleApp: https://heeeju4lov.tistory.com/ 블로그에서 Android + Kotlin 강좌에서 사용함.
github.com