1

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?

3
  • Your x[0], x[18], x[15],... there are String each one? Commented Aug 13, 2015 at 14:51
  • yes each of them are strings Commented Aug 13, 2015 at 14:54
  • Where are the strings? Can you put quotes round the actual strings please. Commented Aug 13, 2015 at 15:11

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.