@@ -406,6 +406,206 @@ class RenderingTests : JupyterReplTestCase() {
406406 }
407407 }
408408
409+ @Test
410+ fun `test sortByColumns by int column` () {
411+ val json = executeScriptAndParseDataframeResult(
412+ """
413+ val df = dataFrameOf("nums")(5, 4, 3, 2, 1)
414+ val res = KotlinNotebookPluginUtils.sortByColumns(df, listOf(listOf("nums")), listOf(false))
415+ KotlinNotebookPluginUtils.convertToDataFrame(res)
416+ """ .trimIndent(),
417+ )
418+
419+ val rows = json[KOTLIN_DATAFRAME ]!! .jsonArray
420+ json.extractColumn<Int >(0 , " nums" ) shouldBe 1
421+ json.extractColumn<Int >(rows.size - 1 , " nums" ) shouldBe 5
422+ }
423+
424+ internal inline fun <reified T > JsonObject.extractColumn (index : Int , fieldName : String ): T {
425+ val element = this [KOTLIN_DATAFRAME ]!! .jsonArray[index].jsonObject[fieldName]!! .jsonPrimitive
426+ return when (T ::class ) {
427+ String ::class -> element.content as T
428+ Int ::class -> element.int as T
429+ else -> throw IllegalArgumentException (" Unsupported type" )
430+ }
431+ }
432+
433+ @Test
434+ fun `test sortByColumns by multiple int columns` () {
435+ val json = executeScriptAndParseDataframeResult(
436+ """
437+ data class Row(val a: Int, val b: Int)
438+ val df = listOf(Row(1, 1), Row(1, 2), Row(2, 3), Row(2, 4), Row(3, 5), Row(3, 6)).toDataFrame()
439+ val res = KotlinNotebookPluginUtils.sortByColumns(df, listOf(listOf("a"), listOf("b")), listOf(true, false))
440+ KotlinNotebookPluginUtils.convertToDataFrame(res)
441+ """ .trimIndent(),
442+ )
443+
444+ json.extractColumn<Int >(0 , " a" ) shouldBe 3
445+ json.extractColumn<Int >(0 , " b" ) shouldBe 5
446+ json.extractColumn<Int >(5 , " a" ) shouldBe 1
447+ json.extractColumn<Int >(5 , " b" ) shouldBe 2
448+ }
449+
450+ @Test
451+ fun `test sortByColumns by single string column` () {
452+ val json = executeScriptAndParseDataframeResult(
453+ """
454+ val df = dataFrameOf("letters")("e", "d", "c", "b", "a")
455+ val res = KotlinNotebookPluginUtils.sortByColumns(df, listOf(listOf("letters")), listOf(true))
456+ KotlinNotebookPluginUtils.convertToDataFrame(res)
457+ """ .trimIndent(),
458+ )
459+
460+ json.extractColumn<String >(0 , " letters" ) shouldBe " e"
461+ json.extractColumn<String >(4 , " letters" ) shouldBe " a"
462+ }
463+
464+ @Test
465+ fun `test sortByColumns by multiple string columns` () {
466+ val json = executeScriptAndParseDataframeResult(
467+ """
468+ data class Row(val first: String, val second: String)
469+ val df = listOf(Row("a", "b"), Row("a", "a"), Row("b", "b"), Row("b", "a")).toDataFrame()
470+ val res = KotlinNotebookPluginUtils.sortByColumns(df, listOf(listOf("first"), listOf("second")), listOf(false, true))
471+ KotlinNotebookPluginUtils.convertToDataFrame(res)
472+ """ .trimIndent(),
473+ )
474+
475+ json.extractColumn<String >(0 , " first" ) shouldBe " a"
476+ json.extractColumn<String >(0 , " second" ) shouldBe " b"
477+ json.extractColumn<String >(3 , " first" ) shouldBe " b"
478+ json.extractColumn<String >(3 , " second" ) shouldBe " a"
479+ }
480+
481+ @Test
482+ fun `test sortByColumns by mix of int and string columns` () {
483+ val json = executeScriptAndParseDataframeResult(
484+ """
485+ data class Row(val num: Int, val letter: String)
486+ val df = listOf(Row(1, "a"), Row(1, "b"), Row(2, "a"), Row(2, "b"), Row(3, "a")).toDataFrame()
487+ val res = KotlinNotebookPluginUtils.sortByColumns(df, listOf(listOf("num"), listOf("letter")), listOf(true, false))
488+ KotlinNotebookPluginUtils.convertToDataFrame(res)
489+ """ .trimIndent(),
490+ )
491+
492+ json.extractColumn<Int >(0 , " num" ) shouldBe 3
493+ json.extractColumn<String >(0 , " letter" ) shouldBe " a"
494+ json.extractColumn<Int >(4 , " num" ) shouldBe 1
495+ json.extractColumn<String >(4 , " letter" ) shouldBe " b"
496+ }
497+
498+ @Test
499+ fun `test sortByColumns by multiple non-comparable column` () {
500+ val json = executeScriptAndParseDataframeResult(
501+ """
502+ data class Person(val name: String, val age: Int) {
503+ override fun toString(): String {
504+ return age.toString()
505+ }
506+ }
507+ val df = dataFrameOf("urls", "person")(
508+ URL("https://example.com/a"), Person("Alice", 10),
509+ URL("https://example.com/b"), Person("Bob", 11),
510+ URL("https://example.com/a"), Person("Nick", 12),
511+ URL("https://example.com/b"), Person("Guy", 13),
512+ )
513+ val res = KotlinNotebookPluginUtils.sortByColumns(df, listOf(listOf("urls"), listOf("person")), listOf(false, true))
514+ KotlinNotebookPluginUtils.convertToDataFrame(res)
515+ """ .trimIndent(),
516+ )
517+
518+ json.extractColumn<Int >(0 , " person" ) shouldBe 12
519+ json.extractColumn<Int >(3 , " person" ) shouldBe 11
520+ }
521+
522+ @Test
523+ fun `test sortByColumns by mix of comparable and non-comparable columns` () {
524+ val json = executeScriptAndParseDataframeResult(
525+ """
526+ val df = dataFrameOf("urls", "id")(
527+ URL("https://example.com/a"), 1,
528+ URL("https://example.com/b"), 2,
529+ URL("https://example.com/a"), 2,
530+ URL("https://example.com/b"), 1,
531+ )
532+ val res = KotlinNotebookPluginUtils.sortByColumns(df, listOf(listOf("id"), listOf("urls")), listOf(true, true))
533+ KotlinNotebookPluginUtils.convertToDataFrame(res)
534+ """ .trimIndent(),
535+ )
536+
537+ json.extractColumn<String >(0 , " urls" ) shouldBe " https://example.com/b"
538+ json.extractColumn<Int >(0 , " id" ) shouldBe 2
539+ json.extractColumn<String >(3 , " urls" ) shouldBe " https://example.com/a"
540+ json.extractColumn<Int >(3 , " id" ) shouldBe 1
541+ }
542+
543+ @Test
544+ fun `test sortByColumns by url column` () {
545+ val json = executeScriptAndParseDataframeResult(
546+ """
547+ val df = dataFrameOf("urls")(
548+ URL("https://example.com/a"),
549+ URL("https://example.com/c"),
550+ URL("https://example.com/b"),
551+ URL("https://example.com/d")
552+ )
553+ val res = KotlinNotebookPluginUtils.sortByColumns(df, listOf(listOf("urls")), listOf(false))
554+ KotlinNotebookPluginUtils.convertToDataFrame(res)
555+ """ .trimIndent(),
556+ )
557+
558+ json.extractColumn<String >(0 , " urls" ) shouldBe " https://example.com/a"
559+ json.extractColumn<String >(1 , " urls" ) shouldBe " https://example.com/b"
560+ json.extractColumn<String >(2 , " urls" ) shouldBe " https://example.com/c"
561+ json.extractColumn<String >(3 , " urls" ) shouldBe " https://example.com/d"
562+ }
563+
564+ @Test
565+ fun `test sortByColumns by column group children` () {
566+ val json = executeScriptAndParseDataframeResult(
567+ """
568+ val df = dataFrameOf(
569+ "a" to listOf(5, 4, 3, 2, 1),
570+ "b" to listOf(1, 2, 3, 4, 5)
571+ )
572+ val res = KotlinNotebookPluginUtils.sortByColumns(df.group("a", "b").into("c"), listOf(listOf("c", "a")), listOf(false))
573+ KotlinNotebookPluginUtils.convertToDataFrame(res)
574+ """ .trimIndent(),
575+ )
576+
577+ fun JsonObject.extractBFields (): List <Int > {
578+ val dataframe = this [KOTLIN_DATAFRAME ]!! .jsonArray
579+ return dataframe.map { it.jsonObject[" c" ]!! .jsonObject[" data" ]!! .jsonObject[" b" ]!! .jsonPrimitive.int }
580+ }
581+
582+ val bFields = json.extractBFields()
583+ bFields shouldBe listOf (5 , 4 , 3 , 2 , 1 )
584+ }
585+
586+ @Test
587+ fun `test sortByColumns for column that contains string and int` () {
588+ val json = executeScriptAndParseDataframeResult(
589+ """
590+ val df = dataFrameOf("mixed")(
591+ 5,
592+ "10",
593+ 2,
594+ "4",
595+ "1"
596+ )
597+ val res = KotlinNotebookPluginUtils.sortByColumns(df, listOf(listOf("mixed")), listOf(true))
598+ KotlinNotebookPluginUtils.convertToDataFrame(res)
599+ """ .trimIndent(),
600+ )
601+
602+ json.extractColumn<String >(0 , " mixed" ) shouldBe " 5"
603+ json.extractColumn<String >(1 , " mixed" ) shouldBe " 4"
604+ json.extractColumn<String >(2 , " mixed" ) shouldBe " 2"
605+ json.extractColumn<String >(3 , " mixed" ) shouldBe " 10"
606+ json.extractColumn<String >(4 , " mixed" ) shouldBe " 1"
607+ }
608+
409609 companion object {
410610 /* *
411611 * Set the system property for the IDE version needed for specific serialization testing purposes.
0 commit comments