将混合的String-Int字符串数字排序为主要顺序,然后按字母顺序在swift中排序

时间:2016-03-17 21:30:49

标签: swift sorting

对于同时具有String和Int值(每个中的一个)的String,可以进行简单排序,将按数字顺序排序的项目作为主要顺序,按字母顺序排列为次要顺序

var nameArray = ["Dave7", "Bob8", "Cathy9", "Henry10", "Susan10", "Pat11", "Steve12", "Dan12", "Ken1", "Sean2", "Howard3", "Dixie3", "Newman5", "Billy6"]

var sortedNameArray = nameArray.sort { $0.compare($1, options: .NumericSearch) == .OrderedAscending }

print(sortedNameArray)  // gives the following:

不想要这个 - > ["Billy6", "Bob8", "Cathy9", "Dan12", "Dave7", "Dixie3", "Henry10", "Howard3", "Ken1", "Newman5", "Pat11", "Sean2", "Steve12", "Susan10"]

即使使用.NumericSearch,结果也是按字母顺序排列的。

我能够使用自定义二叉树获得所需的结果。结果如下:

Ken1 Sean2 Dixie3 Howard3 Newman5 Billy6 Dave7 Bob8 Cathy9 Henry10 Susan10 Pat11 Dan12 Steve12

但是有更简单的解决方案吗?

extension String {

    var integerValue: Int? {
        return Int(self)
    }
}

func extractValueFromString(theString:String)->Int{

    var catNumber: [Character] = []

     //print("theString \(theString)")

    for character in theString.characters{

        var characterString = String(character)

        if var value = characterString.integerValue { //if we don't check program crashes


            //if numberSet.contains(Int(String(character))!) { //another way to check but redundant here

                catNumber.append(character)
               //print(catNumber)
           // }
        }
    }

    let numberString = String(catNumber)

    return Int(numberString)!
}




class Node{

    //nodes now only arrange strings
    var data = ""
    var value = Int()
    var left:Node?;
    var right:Node?;
    deinit {
        //print("deleting \(data)")
       // print("node  deleted")
    }


    init(data:String){
        self.data = data;

        //print(data)
    }

}


class binaryTreeSort{

    var root:Node?

    init(){

    }

    deinit {

        //print("tree  deleted")
    }

    func getRoot()->Node{

        return root!

    }



    func insertNewValue(data:String){

        let newNode = Node(data:data)

        var node:Node? = root

        if (node == nil){
            root = newNode

        }


        while (node != nil) {

            let currentValue = node?.data


            if currentValue == ""{

                node?.data = data
                return
            }

            if currentValue == data {
                //we don't want duplicates.
                return
            }
            if extractValueFromString(currentValue!) <  extractValueFromString(data) {

                if (node!.right != nil) {
                    node = node!.right
                    //print("Going Right at data \(node!.data)")

                }else{
                    node!.right = newNode
                    //print("Going New Right at data \(node!.data)")
                    return
                }
            }else if extractValueFromString(currentValue!) ==  extractValueFromString(data){

                if  currentValue < data {

                    if (node!.right != nil) {
                        node = node!.right
                        //print("Going Right at data \(node!.data)")

                    }else{
                        node!.right = newNode
                        //print("Going New Right at data \(node!.data)")
                        return
                    }



                }else{


                    if (node!.left != nil) {
                        //print("Going Left at data \(node!.data)")
                        node = node!.left
                    }else{
                        node!.left = newNode
                        //print("Going New Left at data \(node!.data)")
                        return
                    }


                }

            }
            else{
                if (node!.left != nil) {
                    //print("Going Left at data \(node!.data)")
                    node = node!.left
                }else{
                    node!.left = newNode
                    //print("Going New Left at data \(node!.data)")
                    return
                }
            }
        }


    }

    func inorderPrint(baseNode:Node){

        if(baseNode.left != nil)
        {
            inorderPrint(baseNode.left!);
            //print("  \(baseNode.data)")
        }




      print("\(baseNode.data)")


        if(baseNode.right != nil)
        {

            inorderPrint(baseNode.right!)
            //print("    \(baseNode.data)")
        }



    }




    func reverseOrderPrint(baseNode:Node){


        if(baseNode.right != nil)
        {

            reverseOrderPrint(baseNode.right!)
            //print("    \(baseNode.data)")
        }



              print("\(baseNode.data)")



        if(baseNode.left != nil)
        {
            reverseOrderPrint(baseNode.left!);
            //print("  \(baseNode.data)")
        }


    }

}

    var myBinaryTreeSort:binaryTreeSort? = binaryTreeSort()

for item in nameArray{
    //print(item)

    myBinaryTreeSort!.insertNewValue(item)
}

myBinaryTreeSort!.inorderPrint(myBinaryTreeSort!.getRoot())
print("---------------")

myBinaryTreeSort!.reverseOrderPrint(myBinaryTreeSort!.getRoot())

myBinaryTreeSort = nil //delete the tree

3 个答案:

答案 0 :(得分:1)

如果您有一个数组,则可以使用自定义闭包进行排序。

例如:

  nameArray.sort({extractValueFromString($0) < extractValueFromString($1)})

会让你亲近。您只需检查它们是否相等,然后返回$0 < $1

答案 1 :(得分:1)

以下是我解决这个问题的方法,做了与@Lou-Franco提到的类似的事情:

func endInteger(word: String) -> Int {
    if let range = word.rangeOfCharacterFromSet(NSCharacterSet.decimalDigitCharacterSet()){
        let numberSubstring = word.substringFromIndex(range.startIndex)
        return Int(numberSubstring) ?? 0
    }
    return 0
}

let sortedArray = yourArray.sort{endInteger($1) > endInteger($0)}

答案 2 :(得分:1)

使用map将名称拆分为多个部分,按数字和名称排序,然后映射以恢复原始名称:

func splitName(name:String) -> (String, Int) {
    if let range = name.rangeOfCharacterFromSet(NSCharacterSet.decimalDigitCharacterSet()) {
     return (name[name.startIndex..<range.startIndex], Int(name[range.startIndex..<name.endIndex])!)
   } else {
        return (name, 0)
    }
}

print(nameArray.map(splitName).sort({ lhs, rhs in
    if lhs.1 < rhs.1 {
        return true
    } else if lhs.1 > rhs.1 {
        return false
    } else {
        return lhs.0 < rhs.0
    }
}).map({ "\($0.0)\($0.1)" }))

可以做的其他一些方法是将元组的元素0保持为全名(带数字),然后最终的地图变为map({ $0.0 })根据大小,这可能比分裂更优化每次比较时的名称。