Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort array by alphabet using Kotlin

Tags:

kotlin

I am making an launcher for my phone and I need to sort the apps by alphabet.

 Appslist = ArrayList<AppInfo>()

    val i = Intent(Intent.ACTION_MAIN, null)
    i.addCategory(Intent.CATEGORY_LAUNCHER)
    val allApps = this.packageManager.queryIntentActivities(i, 0)

    for (ri in allApps) {
        val app = AppInfo()
        app.label = ri.loadLabel(this.packageManager)
        app.packageName = ri.activityInfo.packageName
        app.icon = ri.activityInfo.loadIcon(this.packageManager)
        if(app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.toUpperCase() && searchWord != "" ||
            app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.toLowerCase() && searchWord != "" ||
            app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.capitalize() && searchWord != "" ||
            app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord && searchWord != ""){

            if(app.packageName != "com.david.launcher" ){
                Appslist.add(app)
            }

        }
        if(searchWord == ""){
            if(app.packageName != "com.david.launcher"){
                Appslist.add(app)
            }
        }

    }

Here is my list type (I don't really know if it's called list type, but I hope you'll understand):

public class AppInfo {
internal var label: CharSequence? = null
internal var packageName: CharSequence? = null
internal var icon: Drawable? = null
internal var isInFav: Boolean? = false
like image 493
David Wenzel Avatar asked Nov 17 '18 12:11

David Wenzel


People also ask

How do I sort an array in Kotlin?

To sort an Array of Integers in Kotlin, use Array. sort() method. sort() method sorts the calling array in-place in ascending order. To sort Integer Array in descending order, call sortDescending() method on this Array.

How do I sort an array alphabetically in Android?

To sort the ArrayList, you need to simply call the Collections. sort() method passing the ArrayList object populated with country names. This method will sort the elements (country names) of the ArrayList using natural ordering (alphabetically in ascending order).


1 Answers

The idiomatic way is to use the sortedBy extension method for List if you want to sort into a copy of the list. Or use sortBy extension on a MutableList if you want to sort in-place without a copy. An ArrayList would work as either list type.

// Sort a readonly list into a copy of the list

val appsList: List<AppInfo> = ...

val sortedAppsList = appsList.sortedBy { it.label?.toString() }

versus:

// Sort a mutable list in-place

val appsList: MutableList<AppInfo> = ...

appList.sortBy { it.label?.toString() }

and if holding as an ArrayList it is the same, but not idiomatic to have a reference directly to this concrete type.

// Sort an ArrayList list into a copy of the list

val appsList: ArrayList<AppInfo> = ...  // ALERT! not idiomatic

val sortedAppsList = appsList.sortedBy { it.label?.toString() }

// or if you want, feel free to sort in-place

appsList.sortBy { it.label?.toString() }

Note the toString() on the label: CharSequence member. You have to be careful sorting on a reference of type CharSequence as it is undefined what is its behavior for sorting (see: https://docs.oracle.com/javase/7/docs/api/java/lang/CharSequence.html)

This interface does not refine the general contracts of the equals and hashCode methods. The result of comparing two objects that implement CharSequence is therefore, in general, undefined.

If the CharSequence is already a String (likely is), then there is no harm in calling toString() as it just returns itself.

Also keep in mind that the nullable CharSequence has to be handled as well, and you need to decide where you want nulls: at the start or end of the list. I think the default is for them to go to the start.


Other notes about your code in the question:

Use the List or MutableList interface instead of the concrete class to reference the type, and use the methods from Kotlin stdlib to do actions upon the list. Also use val instead of var for references that will not change (meaning it will always point to the same list regardless of whether the list contents could change).

The big if statement you have can be reduced a lot, go from...

if(app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.toUpperCase() && searchWord != "" ||
    app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.toLowerCase() && searchWord != "" ||
    app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.capitalize() && searchWord != "" ||
    app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord && searchWord != ""){

    if(app.packageName != "com.david.launcher" ){
        Appslist.add(app)
    }

}
if(searchWord == ""){
    if(app.packageName != "com.david.launcher"){
        Appslist.add(app)
    }
}

to simpler:

if (app.packageName != "com.david.launcher" &&
        (searchWord.isBlank() || 
         app.label?.startsWith(searchWord, ignoreCase = true) == true)) {
    appsList.add(app)
}

You should browse the standard library to get an idea of what is available so that you broaden your toolkit for the future.

like image 58
8 revs Avatar answered Sep 21 '22 02:09

8 revs