In Swift, how do I sort an array of strings and have strings of numbers, symbols, etc. always come after alphabetic strings?

前端 未结 3 916
忘掉有多难
忘掉有多难 2021-01-22 21:58

I want to sort an array of strings so that alphabetic characters are always before any other kinds of characters. For example:

[\"800\", \"word\", \"test\"]


        
相关标签:
3条回答
  • 2021-01-22 22:22

    The key is to write your "is ordered before" function to do whatever you want. For example, if by digits, you mean "0"..."9", then something like this is probably what you want:

    func isDigit(c: Character) -> Bool {
        return "0" <= c && c <= "9"
    }
    
    func sortedLettersFirst(lhs: String, rhs: String) -> Bool {
        for (lc, rc) in zip(lhs.characters, rhs.characters) {
            if lc == rc { continue }
    
            if isDigit(lc) && !isDigit(rc) {
                return false
            }
            if !isDigit(lc) && isDigit(rc) {
                return true
            }
            return lc < rc
        }
        return lhs.characters.count < rhs.characters.count
    }
    
    words.sort(sortedLettersFirst)
    

    Of course, if by "digit" you mean "unicode digits", then see What is the replacement for isDigit() for characters in Swift? for a different approach to isDigit. But ultimately, the point is to make whatever rule you want in your isOrderedBefore function, and pass that to sort().

    0 讨论(0)
  • 2021-01-22 22:22

    How about this.

    func sortedNumbersLast(words: [String]) -> [String] {
      var startsWithDigit     = [String]()
      var startsWithCharacter = [String]()
    
      for word in words {
        if let first = word.characters.first {
          if first >= "0" && first <= "9" {
            startsWithDigit.append(word)
          }
          else {
            startsWithCharacter.append(word)
          }
        }
      }
      return startsWithCharacter.sort(<) + startsWithDigit.sort(<)
    }
    

    0 讨论(0)
  • 2021-01-22 22:29

    Try this in Playground, as you can see in the console output it gets the job done, letters are being placed at the front, followed by numbers and other symbols are at the end.

       let stringsSortedByLettersFirstNumbersThenAndOtherSymbolsAtTheEnd: (String, String) -> Bool = { s1, s2 -> Bool in
            guard let f1 = s1.first, let f2 = s2.first else {
                return s1 < s2
            }
            if f1.isLetter == false && f2.isLetter {
                return false
            }
            if f1.isLetter && f2.isLetter == false {
                return true
            }
            if f1.isNumber == false && f2.isNumber {
                return false
            }
            if f1.isNumber && f2.isNumber == false {
                return true
            }
            return s1 < s2
        }
    
        let str = ["4", "A", "B", "Z", "T", "3", "'", "8"]
    
        print(str.sorted(by: stringsSortedByLettersFirstNumbersThenAndOtherSymbolsAtTheEnd))
    

    Above method sorts String in ascending order, if you want to do the other way just change the lines

            return s1 < s2
    

    to

            return s1 > s2
    
    0 讨论(0)
提交回复
热议问题