Kotlin实现List按Price分组并按Rank排序后展示Rank区间的解决方案
Got it, here's a clean, step-by-step Kotlin solution that handles all your requirements perfectly:
First, let's define a data class to match your input structure (this makes working with the list items much cleaner):
data class RankItem( val id: Int, val group_id: Int, val rank: Int, val price: Int, val status: Boolean, val created_at: String, val updated_at: String )
Next, we'll break the solution into three core steps, wrapped into reusable functions:
1. Group by Price & Sort Each Group by Rank
We use Kotlin's standard collection functions to cluster items by their price, then sort each group's items by rank in ascending order (critical for merging consecutive ranks later).
2. Merge Consecutive Ranks into Intervals
A helper function takes a sorted list of RankItems and merges consecutive ranks into human-readable intervals (like "Rank 2-4" instead of separate entries for ranks 2, 3, 4).
3. Format the Final Output
Combine merged rank intervals with their corresponding prices, then join everything into your requested string format.
Full Implementation Code
data class RankItem( val id: Int, val group_id: Int, val rank: Int, val price: Int, val status: Boolean, val created_at: String, val updated_at: String ) fun mergeConsecutiveRanks(rankedItems: List<RankItem>): List<String> { if (rankedItems.isEmpty()) return emptyList() val mergedIntervals = mutableListOf<String>() var currentStart = rankedItems.first().rank var currentEnd = currentStart for (item in rankedItems.drop(1)) { // Check if current rank is consecutive to the end of the current interval if (item.rank == currentEnd + 1) { currentEnd = item.rank } else { // Add the completed interval to the list mergedIntervals.add( if (currentStart == currentEnd) "Rank $currentStart" else "Rank $currentStart-$currentEnd" ) // Reset interval for the next non-consecutive rank currentStart = item.rank currentEnd = currentStart } } // Add the last interval after the loop ends mergedIntervals.add( if (currentStart == currentEnd) "Rank $currentStart" else "Rank $currentStart-$currentEnd" ) return mergedIntervals } fun processRankItems(items: List<RankItem>): String { // Step 1: Group by price, then sort each group by rank val groupedSortedItems = items.groupBy { it.price } .mapValues { (_, group) -> group.sortedBy { it.rank } } // Step 2 & 3: Merge ranks and format output entries val resultEntries = mutableListOf<String>() groupedSortedItems.forEach { (price, sortedItems) -> val mergedRanks = mergeConsecutiveRanks(sortedItems) mergedRanks.forEach { rankInterval -> resultEntries.add("$rankInterval,Price $price") } } // Join all entries with semicolons return resultEntries.joinToString(";") } // Test with your sample data (plus extra entries to demonstrate merging) fun main() { val sampleItems = listOf( RankItem(627, 1, 1, 5000, true, "2021-08-06T12:57:24.000000Z", "2021-08-06T12:57:24.000000Z"), RankItem(628, 1, 2, 1000, true, "2021-08-06T12:57:24.000000Z", "2021-08-06T12:57:24.000000Z"), RankItem(629, 1, 3, 1000, true, "2021-08-06T12:57:24.000000Z", "2021-08-06T12:57:24.000000Z"), RankItem(630, 1, 4, 1000, true, "2021-08-06T12:57:24.000000Z", "2021-08-06T12:57:24.000000Z"), RankItem(631, 1, 5, 500, true, "2021-08-06T12:57:24.000000Z", "2021-08-06T12:57:24.000000Z"), RankItem(632, 1, 6, 500, true, "2021-08-06T12:57:24.000000Z", "2021-08-06T12:57:24.000000Z"), RankItem(633, 1, 7, 500, true, "2021-08-06T12:57:24.000000Z", "2021-08-06T12:57:24.000000Z"), RankItem(634, 1, 8, 500, true, "2021-08-06T12:57:24.000000Z", "2021-08-06T12:57:24.000000Z") ) println(processRankItems(sampleItems)) // Output: Rank 1,Price 5000;Rank 2-4,Price 1000;Rank 5-8,Price 500 }
How It Works
- Grouping & Sorting:
groupBy { it.price }clusters items by their price, thensortedBy { it.rank }ensures each group's items are ordered correctly for consecutive rank checking. - Consecutive Rank Merging: The
mergeConsecutiveRanksfunction tracks the start and end of the current rank interval. When it hits a non-consecutive rank, it finalizes the interval and starts a new one. - Formatting: Each merged interval is paired with its price, then all entries are joined with semicolons to match your requested output format.
内容的提问来源于stack exchange,提问作者Jayesh Shinde

