This tutorial assumes that you know the basics of list. If not, please go over the basic list tutorial. Also you need to know how to use for each number block.
Sorting is arranging of items in a specific order/sequence. There are many algorithms that can be used to sort a list. Here, we will be using Bubble Sort. Bubble Sort is very easy. You start at the beginning of the list, compare each pair of adjacent items and swap if they are not in order. You stop comparing when there is no more items left to compare.
Below is a gif image taken from Wikipedia that shows comparing each pair and swap them if the latter one is smaller/lower than the former one so that the numbers are arranged from smallest to highest which is known as ascending order.
Now that you know about bubble sort, we will go explain how we came up with the procedure SortAndGetList below, step by step. This sort procedure is kind of generic, meaning you can use it for sorting numbers and text both. You can use this procedure for sorting in both ascending and descending orders. Please take note of the numbers in black in the image below as these will be used to describe the purpose of each set of blocks.
We used a procedure result block for sorting. Our procedure SortAndGetList sorts the list in a given order and returns the sorted list. It takes three arguments as follows:
listToSort – This is the list that we want to sort.
order – This tells us how to sort, ascending or descending.
comparisonMode – There are times we will be expecting a list to contain only numbers, sometimes only texts/strings, and sometimes a mixture of both. For numbers, we can easily use Math block’s different operators (=, ≠, >, ≥, <, ≤) to compare two items, but we cannot use those for comparing text/strings as texts are not numbers. In that case, we should use the operators from Text block. For Text block, the comparison uses the alphabetical representation of each character in a piece of text. Please go over the documentation on Text block for better grasp. In Text mode, “a” is higher than “A“; “2” is higher than “11“. Each character has a decimal/numerical representation in Text mode. For instance, the decimal value of ‘A’ is 65, ‘B’ is 66, ‘a’ is 97, ‘0’ is 48, ‘2’ is 50 etc. You can look at the ASCII table for details.
2. We used a do block which acts as a holder/container for result slot. Take a good look at it and you will notice at the bottom of that do block, there’s a result slot which is used to plug the result into so that when some other procedures call this procedure above, they will receive the result plugged into do block.
3. First we check if the list contains at least two items, if not, then there’s not really enough elements to sort as sorting of one element will return that element. Also if you remove that block and the list contains say one item, your app will encounter an error since in the second for each number block we have set from as “number + 1“, but the first element in the list has a position/index of 1, so “number + 1” will be 2 in the first iteration of the second/nested for each number block which doesn’t exist in a list with one item.
4. If you have read on bubble sort algorithm as advised above, you know that we need to compare each adjacent pair. For us to do that, we need one loop to get the items starting from the beginning of the list to the item second to the last in the list to compare. We are not going to compare the last item because there’ll be no item after the last item obviously to compare with. Don’t worry; by that time the last item will be in order as you will see as we move along. In the image above, you can see that in our first for each number, we have a variable named “number” with an initial from value of 1 (because first item in any list is at index 1), increments by 1 (because we want to go through each item) after each iteration, and our loop executes until (to) the value of “number” reaches length of the list minus 1.
5. In the first for each number block, we get an item at position defined by the value of “number” (e.g. if number is 1, we get the first item) and our goal is to compare the item at position pointed by “number” variable with the rest. So, we need another for each number block to get the rest. That is why we have the second for each number block where we have an argument named “number2“, starts from “number + 1” because we want to compare the next item pointed by “number”. We compare each until the end of list including the last item. That is why we didn’t include the last item in the first for loop.
6. We just re-initialized our global variable status to false which we will need later. It’s always better to reinitialize a global variable to its default value for the operation you are performing because other procedures might have used the global variable and changed the value to something else than expected.
7. Storing the item at position pointed by “number” in the list to our global variable named dataHolder1 for later use.
8. We are storing the item at index of “number2” to our global variable named dataHolder2.
9. We check if we should sort the items in ascending order. If so-
10. We need to check if the list should be sorted in number mode, if yes-
11. We compare the item at position “number” with the item at position “number2” using Math block’s “>” operator, and swap the items/values at index “number” and “number2” in the list if the item at position “number” is greater/higher than the item at position “number2” since we will be sorting them in ascending order. If item at “number” is higher, we set the global variable status to true so that we can swap later.
If not in number mode,
12. We do the same comparison as 11 but this time using the comparison operator from Text block. If item at “number” is higher, we set the global variable status to true so that we can swap later.
If we need to sort the items in descending order-
13. Same as 10, check first if the comparison for Descending order should be in number mode. If yes-
14. This is opposite of 11. We use the “<” operator from Math block since this time around we want to swap only if the item at position “number” is less/lower than item at position “number2” since we are sorting the items in descending order. If item at “number” is lower, we set the global variable status to true so that we can swap later.
If not in number mode,
15. We do the same comparison as 14 but this time using the comparison operator from Text block. If item at “number” is lower, we set the global variable status to true so that we can swap later.
16. We simply check if the value of our global variable status is true, if yes–
17. We replace the item at position “number” with the item at position “number2“, and-
18. We replace the item at position “number2” with the item at position “number“.
19. The sorting procedure is done. Hence, we return the sorted list. Note that listToSort argument in our SortAndGetList procedure is simply a reference to the actual list we want to sort. So if we make changes in listToSort, we are actually making changes in the original list that was passed when calling/using SortAndGetList. This makes it unnecessary to return the list. You can use the simple procedure block for that matter rather than using a procedure with result block. To show you how to use it, I used the latter. This tutorial on Procedure With Result has a better example that you should check out.
We can call our SortAndGetList procedure like this-
In the snapshot above, userList is a list. As mentioned, you really don’t need to assign the result of SortAndGetList to userList because when you pass the userList while calling/using SortAndGetList, the changes made in listToSort in SortAndGetList actually changes the userList, as listToSort is just a reference to the userList.
Also, you can simplify SortAndGetList procedure depending on your needs. If you need a procedure for sorting numbers in ascending order, remove the unnecessary blocks (Numbers in black- 9, 10, 12, 13, 14, 15). Also you can remove order and comparisonMode arguments as you don’t need those arguments.
If you need to verify first if a list contains all numbers before you use Math block’s operators for comparing (If you use Math block’s operators for comparing texts, your app will throw an error), you may want to have another procedure that would check if a list contains only numbers like this-
Download the source ListBlocks. There are other features/functionalities that are in source but not covered in this tutorial.
Is it possible to sort lists of lists comparing the variables in the fourth column using this method?
You should be able to sort anything.
To do this, I’ve created two new variable to be compared. How do I get the fourth item out of each list to put into those variables for comparison?
List tutorial (http://imagnity.com/tutorials/app-inventor/list-blocks-on-app-inventor/) explains how to access values at different indices.
Also, when I try to sort a list including Turkish characters like İ, Ş, Ü, or Ö, those are listed at the end of the list, whereas for example İ should be listed after I. is there a way to correct this?
Not sure if AI supports international languages on Text component. You can report this to app inventor. In the meantime, if you are going to use Turkish, you may want to implement the text comparisons yourself. http://stackoverflow.com/questions/3805601/whats-the-quickest-way-to-compare-strings-in-java
how I’m gonna sort numbers in buttons?I got 50 numbers total and get six random numbers from that.And I showing these six numbers in six buttons text property because of the styling easier than labels.Is there a suggestion for that?May I use your sorting algorithm with components?
You have 50 numbers and you want to show 6 of them randomly? In that case, you shuffle the list of your 50 numbers, not sort. After you shuffle your list, show the first 6 numbers from your list. To shuffle, use- http://imagnity.com/tutorials/app-inventor/shuffle-list-unique-random-numbers/
It seems to me a bit weird that App Inventor doesn’t have built-in sorting. Why on earth should I have to build by own sorting procedures?
Is it possible for the code to sort both text alphabetically and numbers in ascending order something like this:
23 – Jan: Birthday wishes!
01 – Jan: Happy new year
01 – Jan: A new year
01 – Jan: A new year
01 – Jan: Happy new year
23 – Jan: Birthday wishes!
In one go, no you cannot. But you can sort them separately. Pass the whole list of texts (e.g. 23 – Jan: Birthday wishes!), but when you compare, just use the numbers (Anything before the dash without spaces). After that, you will need to compare only text part (Anything after dash).
How can I calculate the mode, that is the value more repeats, it’s a statistics aplication
Does this procedure redo itself until it’s completely done?
Please elaborate. The procedure is done in a do loop. Not sure what you meant by redo.
How to order list contains dates in the format dd/mm/yyyy
Regroup them using yyyymmdd format and then you can just treat them as numbers. Just make sure the values are always 8-digit long. For example, Jan 05, 2016 should be 20160105, not 201615 or 2016015 etc.
so i have made an app where its sort of like a pinball game and it saves the players name, the score they recieve and the date when the game has been played. THey are then taken to a another screen where it displays their scores but i cant figure how how to sort it in score order so a highscore table(highest first) can you please help me
You just need to sort using ‘descending’ and number mode.
I’ve made a button for this for when i click a button the list should rearrange itself and go in list order but it doesn’t work can you please tell me why asap
i need to transfer the data from one screen to another please help me
Use TinyDB. You can access the same TinyDB across screens.Also you can pass a value when you open a new screen. Look at this as an example: http://imagnity.com/tutorials/app-inventor/list-view-on-app-inventor/
There is a much easier way :
if you assign a spinner with an unsorted list, it displays as sorted and you can get it back getting elements.
I haven’t tested with other list component and different sort types (numeric : alphabetic) but it can be helpfull in most cases.
I want ask, example i have ababcb then i click button i want change a to be 1, b to be 2, c to be 3 to label. After click button in label to be 121232
I try use if then else but still errror
Sorry for my bad english
Where do you get variables like global status and data holder
Where do you get variables like global status
Thank you for sharing this code!
In order to make it easier to include it in other projects, I replaced the global variables (status, dataHolder1 and dataHolder2) with corresponding local variables declared using the “initialize local” block.
Hi Marcelo, could you provide the block with the modification? I am a newbie in appinventor and I would be very grateful, thank you very much.
Hi, how can I sort the top 5 timestamp using this method?
Username also need to display together with the shortest timestamp.
Here is the screenshots. My blocks cannot works