Last active
March 13, 2016 20:34
-
-
Save robertmryan/ab76052ff4b7dd3eb4a1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: **Sort strings by numeric values only; ignoring non-numeric portions of strings** | |
import Cocoa | |
//: Persuant to [http://stackoverflow.com/a/35962434/1271826](http://stackoverflow.com/a/35962434/1271826), this illustrates a more concise way to accomplish what Mountain Man posted. This suffers from the same limitations as his code, though: | |
//: | |
//: - non-continguous numbers will be treated as single number (e.g. "He is 5 feet 10 inches tall" will be `510`); | |
//: - does not handle negative numbers; and | |
//: - does not handle floating point numbers | |
var unsortedStrings = ["Dave7", "Bob8", "Cathy9", "Henry10", "Susan10", "Pat11", "Steve12", "Dan12", "Ken1", "Sean2", "Howard3", "Dixie3", "Newman5", "Billy6"] | |
let namesSortedByNumber = unsortedStrings | |
.map { string in (string, String(string.characters.filter { $0 >= Character("0") && $0 <= Character("9") })) } | |
.sort { | |
switch $0.1.compare($1.1, options: .NumericSearch) { | |
case .OrderedAscending: | |
return true | |
case .OrderedDescending: | |
return false | |
default: | |
return $0.0.compare($1.0) == .OrderedAscending | |
} | |
}.map { $0.0 } | |
//: This rendition sorts by the first floating point number (including negative numbers) encountered in the strings. This only considers the first number encountered, though. | |
unsortedStrings = ["129 celcius", "110.4 celcius", "-200 celcius"] | |
let regex = try! NSRegularExpression(pattern: "[+-]?\\d+(\\.\\d*)?", options: []) | |
let namesSortedByDecimalNumber = unsortedStrings | |
.map { string -> (String, Double?) in | |
if let match = regex.firstMatchInString(string, options: [], range: NSMakeRange(0, string.characters.count)) { | |
return (string, Double((string as NSString).substringWithRange(match.range))) | |
} else { | |
return (string, nil) | |
} | |
}.sort { | |
if $0.1 == $1.1 { | |
return $0.0 < $1.0 | |
} | |
if $0.1 == nil { | |
return false | |
} else if $1.1 == nil { | |
return true | |
} | |
return $0.1! < $1.1! | |
}.map { $0.0 } | |
//: This rendition sorts by multiple floating point numbers encountered in the strings. | |
unsortedStrings = ["6 feet 1 inch", "5 feet 10 inches", "5 feet 2.5 inches", "5 feet 2 inches", "5 feet 1.5 inches"] | |
let namesSortedByDecimalNumbers = unsortedStrings | |
.map { string -> (String, [Double]) in | |
(string, regex.matchesInString(string, options: [], range: NSMakeRange(0, string.characters.count)) | |
.map { match in Double((string as NSString).substringWithRange(match.range))! }) | |
}.sort { (object0, object1) in | |
for index in (0 ..< (object0.1).count) { | |
if object1.1.count < index { | |
return false | |
} | |
let value0 = object0.1[index] | |
let value1 = object1.1[index] | |
if value0 < value1 { | |
return true | |
} else if value0 > value1 { | |
return false | |
} | |
} | |
if object1.1.count > object0.1.count { | |
return true | |
} | |
return object0.0 < object1.0 | |
}.map { $0.0 } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment