简体   繁体   中英

Swift sort NSArray

I have a problem with my sorting algorithm.

My NSArray (here vcd.signals.key ) contains values of Strings for example:

"x [0]", "x [18]", "x [15]", "x [1]"...

When I try to sort this the result ends up in

"x [0]", "x [15]", "x [18]", "x [1]" 

instead of:

"x [0]", "x [1]", "x [15]", "x [18]"

This is my code:

let sortedKeys = sorted(vcd.signals.keys) {
    var val1 = $0 as! String
    var val2 = $1 as! String

    return val1 < val2
 }

Any idea how I can fix this issue?

Your problem come associated with your comparison , for example see what happen when you compare the two following strings:

println("x [15]" < "x [1]") // true

This is because the default lexicography comparer goes character for character, position by position comparing ,and of course 5 in position 3 is less than ] in position 3:

println("5" < "]") // true

For the explained above you need to create you own comparer but , only compare for the numbers inside the [$0] . For achieve this I use regular expressions to match any numbers inside the brackets like in the following way:

func matchesForRegexInText(regex: String!, text: String!) -> [String] {

    let regex = NSRegularExpression(pattern: regex,
        options: nil, error: nil)!
    let nsString = text as NSString
    let results = regex.matchesInString(text,
        options: nil, range: NSMakeRange(0, nsString.length))
        as! [NSTextCheckingResult]
    return map(results) { nsString.substringWithRange($0.range)}
}

var keysSorted = keys.sorted() {

        var key1 = $0
        var key2 = $1

        var pattern  = "([0-9]+)"   
        var m1 = self.matchesForRegexInText(pattern, text: key1)
        var m2 = self.matchesForRegexInText(pattern, text: key2)

        return  m1[0] < m2[0]
}

In the above regular expression I assume that the numbers only appears inside the brackets and match any number inside the String , but feel free to change the regular expression if you want to achieve anything more. Then you achieve the following:

println(keysSorted) // [x [0], x [1], x [15], x [18]]

I hope this help you.

The issue you are running into is the closing brace character ']' comes after digits. This means that "18" is less than "1]". As long as all your strings share the form of "[digits]" then you can remove the closing brace, sort the strings, add the closing brace back to your final array. The code below works for Swift 2:

let arr = ["x [0]", "x [18]", "x [15]", "x [1]"]
let sorted = arr.map { $0.substringToIndex($0.endIndex.predecessor()) }.sort().map { $0 + "]" }

print(sorted)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM