2

I want to sort a json based on the date inside period but it also contains other string(MAT TY and MAT YA) values which we have to keep in the front of list always(MAT TY first then MAT YA after) and the sorted items after that so how do i do it? Here's the JSON response:

 [{

        "Period": "MAT YA",
        "StartUnit": null,
        "EndUnit": null,

    },
    {

        "Period": "DEC 2018",
        "StartUnit": null,
        "EndUnit": null,

    },
    {

        "Period": "NOV 2018",
        "StartUnit": null,
        "EndUnit": null,

    },
    {

        "Period": "SEP 2018",
        "StartUnit": null,
        "EndUnit": null,

    },
    {

        "Period": "JUN 2019",
        "StartUnit": null,
        "EndUnit": null,

    },
    {

        "Period": "MAT TY",
        "StartUnit": null,
        "EndUnit": null,
    },
    {

        "Period": "MAT YA",
        "StartUnit": null,
        "EndUnit": null,

    },
    {

        "Period": "MAT YA",
        "StartUnit": null,
        "EndUnit": null,

    },
    {

        "Period": "MAT TY",
        "StartUnit": null,
        "EndUnit": null,

    }
]

I know Comparator like this:

myDateList.sortWith(Comparator { s1, s2 -> myDateList.indexOf(s1).compareTo(myDateList.indexOf(s2))})

So how can i convert it to meet the above requirement?

Update: The custom comparator:

 private fun customSortFunction(mydateList: ArrayList<String>){
        val sdf = SimpleDateFormat("MMM yyyy")
        val comparator = Comparator<String> { date1, date2 ->
            if (date1 == "MAT TY") return@Comparator -1
            if (date2 == "MAT TY") return@Comparator 1
            if (date1 == "MAT YA") return@Comparator -1
            if (date2 == "MAT YA") return@Comparator 1

            val date1Formatted = sdf.parse(date1)
            val date2Formatted = sdf.parse(date2)
            return@Comparator date1Formatted.compareTo(date2Formatted)
        }

        mydateList.sortWith(comparator)
        Log.e(TAG, "Date list: "+ mydateList)
    }

StackTrace:

 java.lang.IllegalArgumentException: Comparison method violates its general contract!
        at java.util.TimSort.mergeHi(TimSort.java:899)
        at java.util.TimSort.mergeAt(TimSort.java:516)
        at java.util.TimSort.mergeCollapse(TimSort.java:441)
        at java.util.TimSort.sort(TimSort.java:245)
        at java.util.Arrays.sort(Arrays.java:1523)
        at java.util.Collections.sort(Collections.java:238)
        at kotlin.collections.CollectionsKt__MutableCollectionsJVMKt.sortWith(MutableCollectionsJVM.kt:34)
        at com.abc.ShareStoryFragment.customSortFunction(ShareStoryFragment.kt:429)

And the 429th line is:

mydateList.sortWith(comparator)

Mydatelist values:

[SEP 2019, JUL 2019, AUG 2019, JUN 2019, MAY 2019, APR 2019, MAT TY, MAR 2019, FEB 2019, MAT YA, NOV 2018, SEP 2018, DEC 2018, OCT 2018, JAN 2019, FEB 2019, SEP 2018, JAN 2019, NOV 2018, OCT 2018, DEC 2018, MAT YA, MAT YA, NOV 2018, MAR 2019, MAT TY, SEP 2018, OCT 2018, DEC 2018, APR 2019, JUL 2019, APR 2019, SEP 2019, AUG 2019, MAY 2019, AUG 2019, MAT TY, JAN 2019, FEB 2019, JUN 2019, MAR 2019, MAY 2019, SEP 2019, JUL 2019, JUN 2019, APR 2019, MAR 2019, FEB 2019, MAY 2019, JAN 2019, MAT YA, MAT TY, AUG 2019, DEC 2018, SEP 2019, JUL 2019, NOV 2018, JUN 2019, SEP 2018, OCT 2018, SEP 2019, AUG 2019, JUL 2019, MAY 2019, APR 2019, JUN 2019, MAT TY, MAR 2019, FEB 2019, MAT YA, DEC 2018, OCT 2018, NOV 2018, JAN 2019, SEP 2018, MAT YA, SEP 2018, DEC 2018, OCT 2018, NOV 2018, FEB 2019, JAN 2019, MAR 2019, APR 2019, MAT TY, JUL 2019, MAY 2019, JUN 2019, SEP 2019, AUG 2019, JUN 2019, AUG 2019, SEP 2019, OCT 2018, JUL 2019, SEP 2018, MAY 2019, MAT TY, JAN 2019, NOV 2018, DEC 2018, FEB 2019, MAR 2019, APR 2019, MAT YA]

Please help.

Cosmic Dev
  • 522
  • 6
  • 20

2 Answers2

3

The comparison logic described does not follow the contract. If there is no branch covering when both strings are "MAT YA" or "MAT TY", you can end up with situations where A > B and B > A. You need another condition up top that handles when both strings are the same:

private val val sdf = SimpleDateFormat("MMM yyyy")

fun compare(s1: String?, s2: String?): Int = when {
  s1 == s2 -> 0
  s1 == "MAT TY" -> -1
  s2 == "MAT TY" -> 1
  s1 == "MAT YA" -> -1
  s2 == "MAT YA" -> 1
  s1 == null -> 1
  s2 == null -> -1
  else -> sdf.parse(s1).compareTo(sdf.parse(s2))
}
A. Rager
  • 1,950
  • 2
  • 15
  • 16
1

Here is a custom comparator that meets your need:

val sdf = SimpleDateFormat("MMM yyyy")
val stringList = arrayListOf(
        "JUN 2019",
        "MAT YA",
        "SEP 2018",
        "MAT YA",
        "MAT TY",
        "NOV 2018"
)

val comparator = Comparator<String> { date1, date2 ->
    if (date1 == "MAT TY") return@Comparator -1
    if (date2 == "MAT TY") return@Comparator 1
    if (date1 == "MAT YA") return@Comparator -1
    if (date2 == "MAT YA") return@Comparator 1

    val date1Formatted = sdf.parse(date1)
    val date2Formatted = sdf.parse(date2)
    return@Comparator date1Formatted.compareTo(date2Formatted)
}

stringList.sortWith(comparator)
println(stringList)

This results in:

[MAT TY, MAT YA, MAT YA, SEP 2018, NOV 2018, JUN 2019]
Christilyn Arjona
  • 2,173
  • 3
  • 13
  • 20