@@ -105,86 +105,54 @@ public object KotlinNotebookPluginUtils {
105105 ColumnPath (path)
106106 }
107107
108- val comparator = createComparator(sortKeys, isDesc)
108+ val comparator = createComparator(df, sortKeys, isDesc)
109109
110110 return df.sortWith(comparator)
111111 }
112112
113- private fun createComparator (sortKeys : List <ColumnPath >, isDesc : List <Boolean >): Comparator <DataRow <* >> {
114- return Comparator { row1, row2 ->
115- for ((key, desc) in sortKeys.zip(isDesc)) {
116- val column = row1.df().getColumn(key)
117- val comparisonResult = if (column.valuesAreComparable()) {
118- compareComparableValues(row1, row2, key, desc)
119- } else if (column.isFrameColumn()) {
120- val firstValue = column[row1].rowsCount()
121- val secondValue = column[row2].rowsCount()
122- firstValue.compare(secondValue, desc)
123- } else if (column.isList()) {
124- compareListSizes(row1, row2, key, desc)
125- } else {
126- compareStringValues(row1, row2, key, desc)
113+ private fun createComparator (
114+ df : AnyFrame ,
115+ sortKeys : List <ColumnPath >,
116+ isDesc : List <Boolean >,
117+ ): Comparator <DataRow <* >> {
118+ val columnComparators = sortKeys.zip(isDesc).map { (key, desc) ->
119+ val column = df.getColumn(key)
120+ createColumnComparator(column, desc)
121+ }
122+
123+ return when (columnComparators.size) {
124+ 1 -> columnComparators.single()
125+
126+ else -> Comparator { row1, row2 ->
127+ for (comparator in columnComparators) {
128+ val result = comparator.compare(row1, row2)
129+ // If a comparison result is non-zero, we have resolved the ordering
130+ if (result != 0 ) return @Comparator result
127131 }
128- // If a comparison result is non-zero, we have resolved the ordering
129- if (comparisonResult != 0 ) return @Comparator comparisonResult
132+ // All comparisons are equal
133+ 0
130134 }
131- // All comparisons are equal
132- 0
133135 }
134136 }
135137
136- private fun compareListSizes (
137- row1 : DataRow <* >,
138- row2 : DataRow <* >,
139- key : ColumnPath ,
140- desc : Boolean ,
141- ): Int {
142- val firstValue = (row1.getValueOrNull(key) as ? List <* >)?.size ? : 0
143- val secondValue = (row2.getValueOrNull(key) as ? List <* >)?.size ? : 0
144- return if (desc) {
145- secondValue.compareTo(firstValue)
146- } else {
147- firstValue.compareTo(secondValue)
148- }
149- }
138+ private fun createColumnComparator (column : AnyCol , desc : Boolean ): Comparator <DataRow <* >> {
139+ val comparator: Comparator <DataRow <* >> = when {
140+ column.valuesAreComparable() -> compareBy(nullsLast()) {
141+ column[it] as Comparable <Any ?>?
142+ }
150143
151- @Suppress(" UNCHECKED_CAST" )
152- private fun compareComparableValues (
153- row1 : DataRow <* >,
154- row2 : DataRow <* >,
155- key : ColumnPath ,
156- desc : Boolean ,
157- ): Int {
158- val firstValue = row1.getValueOrNull(key) as Comparable <Any ?>?
159- val secondValue = row2.getValueOrNull(key) as Comparable <Any ?>?
160-
161- return when {
162- firstValue == null && secondValue == null -> 0
163- firstValue == null -> if (desc) 1 else - 1
164- secondValue == null -> if (desc) - 1 else 1
165- desc -> secondValue.compareTo(firstValue)
166- else -> firstValue.compareTo(secondValue)
167- }
168- }
144+ // Comparator shows a slight improvement in performance for this case
145+ column.isFrameColumn() -> Comparator { r1, r2 ->
146+ column[r1].rowsCount().compareTo(column[r2].rowsCount())
147+ }
148+
149+ column.isList() -> compareBy { (column[it] as ? List <* >)?.size ? : 0 }
169150
170- private fun compareStringValues (
171- row1 : DataRow <* >,
172- row2 : DataRow <* >,
173- key : ColumnPath ,
174- desc : Boolean ,
175- ): Int {
176- val firstValue = (row1.getValueOrNull(key)?.toString() ? : " " )
177- val secondValue = (row2.getValueOrNull(key)?.toString() ? : " " )
178-
179- return if (desc) {
180- secondValue.compareTo(firstValue)
181- } else {
182- firstValue.compareTo(secondValue)
151+ else -> compareBy { column[it]?.toString() ? : " " }
183152 }
153+ return if (desc) comparator.reversed() else comparator
184154 }
185155
186- private fun <T : Comparable <T >> T.compare (other : T , desc : Boolean ) = if (desc) other.compareTo(this ) else this .compareTo(other)
187-
188156 internal fun isDataframeConvertable (dataframeLike : Any? ): Boolean =
189157 when (dataframeLike) {
190158 is Pivot <* >,
@@ -262,6 +230,7 @@ public object KotlinNotebookPluginUtils {
262230
263231 is FormattedFrame <* > -> dataframeLike.df
264232
233+ // мб повыше перенести
265234 is AnyFrame -> dataframeLike
266235
267236 is AnyRow -> dataframeLike.toDataFrame()
0 commit comments