Swift sorting array of structs by string double
You can convert the weekFTC
string to a Double
and then compare, like so:
users.sort { (lhs, rhs) -> Bool in
let lhsVal = Double(lhs.weekFTC) ?? 0
let rhsVal = Double(rhs.weekFTC) ?? 0
return lhsVal > rhsVal
}
Comparing strings directly does a lexicographical comparison.
Example:
var array = ["111", "e3", "22"]
array.sort { (lhs, rhs) -> Bool in
return lhs > rhs
}
print(array) //["e3", "22", "111"]
So we should see if the string can be made into a number and then sort.
This time it will do a numeric comparison, like so:
var array = ["111", "e3", "22"]
array.sort { (lhs, rhs) -> Bool in
let lhs = Double(lhs) ?? 0
let rhs = Double(rhs) ?? 0
return lhs > rhs
}
print(array) //["111", "22", "e3"]
Swift - Sort array of objects with multiple criteria
Think of what "sorting by multiple criteria" means. It means that two objects are first compared by one criteria. Then, if those criteria are the same, ties will be broken by the next criteria, and so on until you get the desired ordering.
let sortedContacts = contacts.sort {
if $0.lastName != $1.lastName { // first, compare by last names
return $0.lastName < $1.lastName
}
/* last names are the same, break ties by foo
else if $0.foo != $1.foo {
return $0.foo < $1.foo
}
... repeat for all other fields in the sorting
*/
else { // All other fields are tied, break ties by last name
return $0.firstName < $1.firstName
}
}
What you're seeing here is the Sequence.sorted(by:)
method, which consults the provided closure to determine how elements compare.
If your sorting will be used in many places, it may be better to make your type conform to the Comparable
protocol. That way, you can use Sequence.sorted()
method, which consults your implementation of the Comparable.<(_:_:)
operator to determine how elements compare. This way, you can sort any Sequence
of Contact
s without ever having to duplicate the sorting code.
How do I sort an array of structs by multiple values?
I'm not yet proficient in Swift, but the basic idea for a multiple-criteria sort is:
let sorted = conditions.sorted { (lhs: Condition, rhs: Condition) -> Bool in
if lhs.set == rhs.set {
return lhs.someString < rhs.someString
}
return (lhs.set) < (rhs.set)
}
Sort an array of Object by one of their Double parameter
Computing the distance between lat/long pairs is pretty time-consuming. Your code is repeating that conversion twice for every comparison. Don't do that. For a really good sort algorithm, that will convert your lat/long pairs to distances about 2•n•log(n) times
Is your var distanceToUsersCurrentLocation
a property of the objects in your array? If so, change it to be a lazy var. That way, it will be computed the first time you need it and then treated as a constant thereafter.
In order to use a lazy var, your object will need to be a class, not a struct (a reference type, not a value type.)
If your data object is a struct and you can't change it to class, you might need to map your array of structs to an array of tuples of type (Chantier, Double), sort the array of tuples, and maps that resulting array back an array of Chantier objects
Sort function does not sort my structure in Swift
Your sort isn't working as expected because you are sorting the firstColumn
as a String
. When treated as a String
, 1000.0
comes before 12.0
so you won't get the firstColumn
sorted in numerical order.
If you can store your firstColumn
as a Double
, then do so.
Otherwise, you can convert the values while sorting with this:
shares.sort(by:{ Double($0.firstColumn) ?? 0 < Double($1.firstColumn) ?? 0 })
Note: Since not all String
s can be converted to Double
, the conversion returns a Double?
that is nil
when the conversion fails. The nil coalescing operator ??
is used to replace the failed cases with 0
. If you're sure all of the values will convert, then ??
just unwraps the converted value.
Sort array of objects by two properties
Yes there is a very simple way using the Array.sort()
Code:
var sorted = array.sorted({ (s1, s2) -> Bool in
if s1.isPriority && !s2.isPriority {
return true //this will return true: s1 is priority, s2 is not
}
if !s1.isPriority && s2.isPriority {
return false //this will return false: s2 is priority, s1 is not
}
if s1.isPriority == s2.isPriority {
return s1.ordering < s2.ordering //if both save the same priority, then return depending on the ordering value
}
return false
})
The sorted array:
true - 10
true - 10
true - 12
true - 12
true - 19
true - 29
false - 16
false - 17
false - 17
false - 17
false - 18
Another a bit shorter solution:
let sorted = array.sorted { t1, t2 in
if t1.isPriority == t2.isPriority {
return t1.ordering < t2.ordering
}
return t1.isPriority && !t2.isPriority
}
Related Topics
Linking Error When Building Parse in Xcode 7
Tube Physics Body Acting Like Scncylinder, But How to Make It Act Like Scntube
How to Decrease a Value Using Fieldvalue in Firestore (Swift)
Swift Decodable, Endpoint Returns Completely Different Types
How to Move a Model and Generate Its Collision Shape at the Same Time
How to Handle Two Possible Date Formats
How to Stop Tokbox Screen Sharing in Swift
How to Make a Uiview Grow in Uiview.Animate() with an Accurate Corner Radius
How to Get All Text from a PDF in Swift
Swift Access Array with Index Gives Following Error. Any Idea Why
Swift: Call Self Method Inside Init
Could Not Cast Value of Type Uiview to [Customview] Using Xib
Can the Byte Order of Double Be Safely Reversed
Any Way to Get a Gif as a Background with Swiftui
Realm Error Domain=Io.Realm.Unknown Code=89 "Operation Canceled"