1. Introduction

Sorting elements in lexicographical order means arranging them alphabetically. For example, given a list of words [“banana”, “Apple”, “cherry”, “Date”], sorting them in lexicographical order would result in [“Apple”, “banana”, “cherry”, “Date”]. Notice that the case of characters is ignored while sorting. This can be useful when working with case-insensitive data related to strings, names, or any other data that needs to be arranged alphabetically.

In this tutorial, we’ll explore different methods we can use to sort elements in lexicographical order in Kotlin.

2. Using Iteration

Our first method involves implementing the logic to perform the sorting ourselves. Principally, we iterate our List or Array of strings one String at a time, and for each String of words[i], we compare it with all other strings in front of it in the Array words[j].

This comparison uses the ASCII codes for characters and could yield results such as [“Union”, “apple”]. So, to sort the strings without case sensitivity, we need to convert each string to lowercase() before performing the comparison:

fun sortWithCustomMethod(words: Array<String>){
    for (i in 0..words.size - 2) {
        for (j in i + 1 until words.size) {
             if (words[i].lowercase() > words[j].lowercase()) {
                val temp = words[i]
                words[i] = words[j]
                words[j] = temp
            }
        }
    }
}

Let’s test this method for correctness:

@Test
fun `sort using custom method`(){
    val words = arrayOf("banana", "apple", "cherry", "date", "A", "Result", "Union")

    sortWithCustomMethod(words)
    assertContentEquals(arrayOf("A", "apple", "banana", "cherry", "date", "Result", "Union"), words)
}

3. Using the forEach() Method

Alternatively, we can safely deal with the iteration approach by using forEach() lambdas to iterate every element of the List. Therefore, we can use a similar logic as above without needing to worry about selecting the correct limits of our loops:

fun sortStringsIgnoreCaseForEach(words: List<String>): List<String> {
    val sortedWords = words.toMutableList()
    sortedWords.forEachIndexed { i, word ->
        (i until sortedWords.size).forEach { j ->
            if (word.lowercase().compareTo( sortedWords[j].lowercase()) > 0) {
                sortedWords[i] = sortedWords[j].also { sortedWords[j] = sortedWords[i] }
            }
        }
    }
    return sortedWords
}

As usual, let’s test this method as well:

@Test
fun `sort using forEachIndexed method`(){
    val words = listOf("banana", "apple", "cherry", "date", "A", "Result", "Union")

    val sortedWords = sortStringsIgnoreCaseForEach(words)
    assertContentEquals(
        listOf("A", "apple", "banana", "cherry", "date", "Result", "Union"),
        sortedWords
    )
}

4. Using the sortedWith() Function With a Custom Comparator

We can also use the sortedWith() function. This method is a built-in function in Kotlin that we can use to sort elements in a List. It returns a sorted list in ascending order by default. Finally, to sort the strings in lexicographical order, we can pass a Comparator that compares the elements using their natural order:

@Test
fun `sort using sortedWith() method`(){
    val words = arrayOf("banana", "apple", "cherry", "date", "A", "Result", "Union")
    val sortedWords = words.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it })

    assertContentEquals(
        listOf("A", "apple", "banana", "cherry", "date", "Result", "Union"),
        sortedWords
    )
}

Here, we’ve used the String.CASE_INSENSITIVE_ORDER parameter — a built-in Comparator we can use to sort the strings by their natural order.

5. Using the sortedBy() Function With a Custom Mapping Function

The sortedBy() function is another built-in function in Kotlin that we can use to sort elements in a list. It accepts a lambda expression that maps each element to a comparable value as an argument. To sort elements in lexicographical order while ignoring case, we can sort each element by its lowercase representation:

@Test
fun `sort using sortedBy() method`(){
    val words = arrayOf("banana", "apple", "cherry", "date", "A", "Result", "Union")
    val sortedWords = words.sortedBy { it.lowercase() }

    assertContentEquals(
        listOf("A", "apple", "banana", "cherry", "date", "Result", "Union"),
        sortedWords
     )
}

6. Conclusion

In this article, we’ve explored different ways to sort strings in lexicographical order in Kotlin while ignoring the case of characters. By using these techniques, we can easily perform a dictionary sort on a list of strings.