Reputation: 353
This piece of code sorts an array of strings by placing strings with a specific prefix 'searchTerm' at the beginning of the array, and strings that don't have that prefix at the end. Can someone explain how this function works? I'm new at developing in Swift if you couldn't already tell, so please keep the explanation as SIMPLE as possible. Thank you!
stringArray = stringArray.sorted(by: {
switch ($0.hasPrefix(searchTerm), $1.hasPrefix(searchTerm) {
case (true, true): return $0 < $1 ;
case (true, false): return true ;
case (false, true): return false ;
case (false, false): return $0 < $1
}
})
Upvotes: 3
Views: 386
Reputation: 150685
The sorted method you are using runs through the array sorting the items according to the criteria you provide in the block. This block needs to return true
if one item ($0) should be ordered before the other ($1)
Since you are sorting first on if there is a prefix before the value of the string the comparison is being made like this:
switch ($0.hasPrefix(searchTerm), $1.hasPrefix(searchTerm) {
case (true, true): return $0 < $1 ; // If both items have the prefix, just sort them the way strings are normally sorted
case (true, false): return true ; // Since the first item has a prefix and the second does not, it should appear before the second one, so return true.
case (false, true): return false ; // Since the second item has a prefix, and the first one does not, the first item should be sorted after the second, so return false
case (false, false): return $0 < $1 // Since neither items have a prefix, just sort them the way strings are normally sorted.
}
An alternative way to do this which might be clearer:
array.sorted { (first, second) -> Bool in
switch (first.hasPrefix("p"), second.hasPrefix("p")) {
case (true, true), (false, false): return first < second
case (true, false): return true
case (false, true): return false
}
}
Upvotes: 3
Reputation: 63369
sorted(by:)
lets you specify your own sorting criteria. It performs the sorting by repeatedly asking you how certain elements compare to each other, by running the closure you gave it and passing in the elements as parameters.
This closure comes down to four possible cases:
case (true, true): return $0 < $1
If both $0
and $1
start with searchTerm
, then the ordering between them is decided by regular string comparison ($0 < $1
)
case (true, false): return true
If $0
starts with searchTerm
, but $1
doesn't, then $0
should come before $1
case (false, true): return false
If $0
starts with searchTerm
, but $1 doesn't, then $1
should come after $0
case (false, false): return $0 < $1
If neither $0
nor $1
start with searchTerm
, then the ordering between them is decided by regular string comparison ($0 < $1
)
Upvotes: 1
Reputation: 2177
stringArray = stringArray.sorted(by: {
Here, you are reassigning stringArray
to be the sorted version of itself. The inclusion of the by
parameter indicates to Swift that you would like it to use your own sorting order instead of the default one (in this case, things that begin with "searchTerm" come before anything else).
To describe your sorting order, you use a comparison function -- a piece of code that takes two elements from your array and compares them. Let's call these elementA
and elementB
. If elementA
should come before elementB
, your code should return true
. If elementB
should come before elementA
, your code should return false
. By using your code to determine which elements come before other elements, Swift can sort your array based on this specification.
switch ($0.hasPrefix(searchTerm), $1.hasPrefix(searchTerm) {
This line takes the two elements ($0
and $1
) and checks if they begin with "searchTerm." For each case, the two booleans in the expression indicate if $0
and $1
start with "searchTerm" respectively.
case (true, true): return $0 < $1 ;
Both of these elements start with "searchTerm," so you want to return the natural ordering (i.e. alphabetical ordering). You let Swift use the standard comparison operator, because $0 < $1
will return true
if $0
comes before $1
and false
otherwise.
case (true, false): return true ;
$0
starts with "searchTerm," but $1
does not. You want $0
to come before $1
, so you return true
.
case (false, true): return false ;
$0
does not start with "searchTerm," but $1
does. You want $1
to come before $0
, so you return false
.
case (false, false): return $0 < $1
Neither $0
nor $1
start with "searchTerm", so you use natural ordering again.
Upvotes: 1
Reputation: 54755
The sorted(by:)
function takes a closure as its input parameter, where you can define your own sorting function. The function iterates through the array in element pairs.
$0
and $1
are so called anonymous closure parameters, in this case, $0
is the current element and $1
is the next element.
The switch statement checks whether the current or the next element starts with the string that's stored in the searchTerm
variable.
The different states of the switch statement define how the elements should be sorted. If both or neither of the elements have the prefix, they are alphabetically sorted. If only one of them has the prefix, the one that has it will come first in the sorted array.
Hope my explanation was sufficient, if not, just tell me what should I clarify in more detail.
Upvotes: 2