This tutorial assumes that you know the basic of list. If not, please go over the basic list tutorial. Also you need to know how to use for range 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 method is kind of generic, meaning you can use it for sorting numbers and text both. Please take note of the numbers in red in the image below as these will be used to describe the purpose of each set of blocks.
We used a procedure with 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:
1. listToSort - This is the list that we want to sort.
2. order - This tells us how to sort, ascending or descending.
3. 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 (=, >, <, not=, >=, <=) 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 a 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.
4. 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 range block we have set start as "i+1", but the first element in the list has a position/index of 1, so "i + 1" will be 2 in the first iteration of the second/nested for range block which doesn't exist in a list with one item.
5. If you have read on bubble sort algorithm as advised above, you should know that we need to compare each adjacent pair. For us to do that, we need one loop (you can use any of the blocks - foreach, for range, or while with some counters to keep track of indexes/positions) to get items starting from the beginning of the list to the item second to the last in the list at a time. 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 range, we have an argument named "i" with an initial value of 1 (because start set to 1), increments by 1 (because step set to 1) after each iteration, and iteration/looping stops when the value of "i" reaches length of the list minus 1.
6. In the first for range block, we get an item at position defined by the value of "i" (e.g. if i is 1, we get the first item) and our goal is to compare the item at position "i" with the rest. So, we need another for range block to get the rest. That is why we have the second for range block where we have an argument named "j", start of "j" is set to "i+1" because we don't want to compare "i" with "i", the step is set to 1, and end is set to the size/length of the list as we want all items to be compared with the item at position "i".
7. We just re-initialized our global variable status to false which we will need later.
8. Storing the value/item at position/index of "i" in the list to our global variable named dataHolder. It's ok if you don't want to store this separately in a variable, but this will make you repeat the same set of blocks multiple times which would make the procedure too crowded to read.
9. We are storing the value/item at position/index of "j" to our global variable named dataHolder2.
10. We check if we should organize/sort the items in ascending order. If so-
11. We need to check if the list should be sorted in number mode, if yes-
12. We compare the item at position "i" with the item at position "j" using Math block's ">" operator, and swap the items/values at "i" and "j" in the list if the item at position "i" is greater/higher than the item at position "j" since we will be sorting them in ascending order. If item at "i" is higher, we set the global variable status to true so that we can swap later.
If not in number mode,
13. We do the same comparison as 12 but this time using the comparison operator from Text block. If item at "i" 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-
14. Same as 11, check first if the comparison for Descending order should be in number mode. If yes-
15. This is opposite of 12. We use the "<" operator from Math block since this time around we want to swap only if the item at position "i" is less/lower than item at position "j" since we are sorting the items in descending order. If item at "i" is lower, we set the global variable status to true so that we can swap later.
If not in number mode,
16. We do the same comparison as 15 but this time using the comparison operator from Text block. If item at "i" is lower, we set the global variable status to true so that we can swap later.
17. We simply check if the value of our global variable status is true, if yes-
18. We replace the item at position "i" with the item at position "j", and-
19. We replace the item at position "j" with the item at position "i".
20. 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 procedureWithResult block. For readability convenience, I used the latter.
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 red - 10, 11, 13, 14, 15, 16). Also you can remove 2 and 3 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.zip from Downloads page and try it for yourself. There are other features/functionalities that are in source but not covered in this tutorial.