Swift Sorting Array of Structs by String Double

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 Contacts 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 Strings 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



Leave a reply



Submit