39
myArray = [Step 6, Step 12, Step 5, Step 14, Step 4, Step 11, Step 16, Step 9, 
Step 3, Step 13, Step 8, Step 2, Step 10, Step 7, Step 1, Step 15]

How can I sort this array above in this way?

[Step 1, Step 2, Step 3, Step 4, ....]

I used this function in swift sort(&myArray,{ $0 < $1 }) but it was sorted this way

[Step 1, Step 10, Step 11, Step 12, Step 13, Step 14, Step 15, Step 16, Step 2, 
 Step 3, Step 4, Step 5, Step 6, Step 7, Step 8, Step 9]
1

8 Answers 8

62

Another variant is to use localizedStandardCompare:. From the documentation:

This method should be used whenever file names or other strings are presented in lists and tables where Finder-like sorting is appropriate.

This will sort the strings as appropriate for the current locale. Example:

let myArray = ["Step 6", "Step 12", "Step 10"]

let ans = sorted(myArray,{ (s1, s2) in 
    return s1.localizedStandardCompare(s2) == NSComparisonResult.OrderedAscending
})

println(ans)
// [Step 6, Step 10, Step 12]

Update: The above answer is quite old and for Swift 1.2. A Swift 3 version is (thanks to @Ahmad):

let ans = myArray.sorted {
    (s1, s2) -> Bool in return s1.localizedStandardCompare(s2) == .orderedAscending
}

For a different approach see https://stackoverflow.com/a/31209763/1187415, translated to Swift 3 at https://stackoverflow.com/a/39748677/1187415.

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

8 Comments

let ans = anArray.sorted{$0.localizedStandardCompare($1) == NSComparisonResult.OrderedAscending} sortedArray
@LeoDabus, that's shorter, but I find my and Martin's (slightly longer) syntax a little easier to read at a glance, especially for newbies.
Hi Martin, Thank you for answering and for me this is the best answer also like comment of Ludovic
Swift 3 version: let myArray = ["Step 6", "Step 12", "Step 10"] let ans = myArray.sorted { (s1, s2) -> Bool in return s1.localizedStandardCompare(s2) == ComparisonResult.orderedAscending }
@MartinR Xcode 13+ • iOS 15+ you can use KeyPathComparator passing self and String.Comparator.localizedStandard Swift sort an array with strings and numbers.
|
18

The Swift 3 version of Duncan C's answer is

let myArray = ["Step 6", "Step 12", "Step 10"]

let sortedArray = myArray.sorted {
    $0.compare($1, options: .numeric) == .orderedAscending
}

print(sortedArray) // ["Step 6", "Step 10", "Step 12"]

Or, if you want to sort the array in-place:

var myArray = ["Step 6", "Step 12", "Step 10"]

myArray.sort {
    $0.compare($1, options: .numeric) == .orderedAscending
}

print(myArray) // ["Step 6", "Step 10", "Step 12"]

Comments

7

NSString has a rich set of methods for comparing strings. You can use the method compare:options:.

You'll want the NSNumericSearch option. If you read the description of that option, it says:

Numbers within strings are compared using numeric value, that is, Name2.txt < Name7.txt < Name25.txt.

So you could write a Swift sort line that does what you want using that function.

Something like this:

let myArray = ["Step 6", "Step 12", "Step 10"]

let ans = myArray.sorted {
    (first, second) in
    first.compare(second, options: .NumericSearch) == NSComparisonResult.OrderedAscending
}

println(ans)
// [Step 6, Step 10, Step 12]

3 Comments

Casting to NSString is not necessary. As long as Foundation is imported, the methods are available for String as well.
Hi Duncan C, Thank you for the time answering my question your answer is correct I appreciate it but I find a better answer.
If you found a better answer then you should post it as an answer to your own question and accept it.
6

In Swift 2:

import Foundation

let myArray = ["Step 6", "Step 12", "Step 10"]

extension String {
  func extractIntFromEnd() -> Int? {
    return self.componentsSeparatedByString(" ").last.flatMap{Int($0)}
  }
}

let ans = myArray.sort {
  (first, second) in
  first.extractIntFromEnd() < second.extractIntFromEnd()
}

In Swift 1:

let myArray = ["Step 6", "Step 12", "Step 10"]

extension String {
  func extractIntFromEnd() -> Int? {
    return self.componentsSeparatedByString(" ").last.flatMap{$0.toInt()}
  }
}

let ans = myArray.sorted {
  (first, second) in
  first.extractIntFromEnd() < second.extractIntFromEnd()
}

In both, this array:

let myArray = [
  "Step 6" ,
  "Step 12",
  "Step 5" ,
  "Step 14",
  "Step 4" ,
  "Step 11",
  "Step 16",
  "Step 9" ,
  "Step 3" ,
  "Step 13",
  "Step 8" ,
  "Step 2" ,
  "Step 10",
  "Step 7" ,
  "Step 1" ,
  "Step 15"
]

Will give you this answer:

["Step 1", "Step 2", "Step 3", "Step 4", "Step 5", "Step 6", "Step 7", "Step 8", "Step 9", "Step 10", "Step 11", "Step 12", "Step 13", "Step 14", "Step 15", "Step 16"]

(In the Swift 2.0 version, you should be able to do last.flatMap(Int.init), but it's not working for me for some reason. Even something like ["1", "2"].flatMap(Int.init) is crashing my playground. Looks like a bug.)

1 Comment

Hi oisdk, Thank you for the time answering I appreciate your answer it was also correct but I find a better answer
1

let myArray = ["Step 6", "Step 12", "Step 10"]

let sortedArray = myArray.sorted(by: { x, y in return x.field.name.compare(y.field.name, options: .numeric, range: nil, locale: nil) == .orderedAscending })

Comments

0
NSArray *assorted = [@"1 2 3 9 ; : 구 , 결 A B C Z ! á" componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSArray *sorted = [assorted sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    /* NSOrderedAscending, NSOrderedSame, NSOrderedDescending */
    BOOL isPunct1 = [[NSCharacterSet punctuationCharacterSet] characterIsMember:[(NSString*)obj1 characterAtIndex:0]];
    BOOL isPunct2 = [[NSCharacterSet punctuationCharacterSet] characterIsMember:[(NSString*)obj2 characterAtIndex:0]];
    if (isPunct1 && !isPunct2) {
        return NSOrderedAscending;
    } else if (!isPunct1 && isPunct2) {
        return NSOrderedDescending;
    }
    return [(NSString*)obj1 compare:obj2 options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch|NSNumericSearch]|;         
}];

Comments

0

Sorting in Swift 2.0 Demo link, change of syntax from "sorted(myArray,{})" to "myArray.sort({})". Extensible Protocol.

let myArray = ["Step 6", "Step 12", "Step 10"]
let sortedArray = myArray.sort({ x, y in
    return x.localizedStandardCompare(y) == NSComparisonResult.OrderedAscending
})

dump(sortedArray)

Swift 1.2 Demo

Comments

-1

You can use a loop equal to length of the array, i.e. for(i=0;i<myArray.length;i++) and then can use a variable to sort them in order like:

for (int i = 0; i < myArray.length; i++) 
{
  for (int j = i + 1; j < n; j++) 
  {
    if (a[i] > a[j]) 
    {
      temp = a[i];
      a[i] = a[j];
      a[j] = temp;
    }
  }
}

1 Comment

This does not address the problem of sorting strings according to their numerical value (e.g. "Step 6" < "Step 10" < "Step 12"). Also this does not compile in Swift.

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.