【问题标题】:How to sort an array with string in it in Swift?如何在 Swift 中对包含字符串的数组进行排序?
【发布时间】:2016-05-01 21:18:57
【问题描述】:

我有这些数组:

ArrayEntr = ["Hello (40 km)", "Salut (20 km)", "Bonjour (30 km)", "Hi (35 km)"]
ArraySorted = ["20", "30", "35", "40"]

我想以与 ArraySorted 相同的顺序替换 ArrayEntr。其实我是想ArrayEntr 以最后的数字升序排列

我已经尝试了几个循环,但我无法让它按我想要的方式工作。

非常感谢!

【问题讨论】:

  • "我已经尝试了几个循环" 给我们展示其中的一些。你知道如何找到隐藏在字符串中的数字吗?

标签: ios arrays swift sorting


【解决方案1】:

既然您知道您将需要这样做,请提前计划;将原始数组形成为 string-Int 元组数组:

ArrayEntr = [("Hello (40 km)",40), ("Salut (20 km)",20), ("Bonjour (30 km)",30), ("Hi (35 km)",35)]

现在问题很简单:只需对每种类型的第二个成员进行排序,即$0.1

如果你不这样做,你将不得不以某种方式找到隐藏在每个字符串中的数字。你可以这样做,但你大概在某个时候有一个数字,所以把它埋在一个字符串中只是为了让它很难再把它找回来似乎很愚蠢。

【讨论】:

    【解决方案2】:

    如果您从不提供数字信息和字符串的外部来源获取此数组,则您必须自己从中提取数字。当然,如果你在某个时候有数字信息,你应该把它挂在 @matt says 上。

    从字符串中取回数字信息的一种方法是在数组上使用flatMap,然后使用stringByTrimmingCharactersInSet 以去除字符串每一端的非数字字符。然后,您可以尝试从中创建一个 double 以创建一个新的 (String, Double) 元组数组,并使用 flatMap 过滤掉 nil 结果。例如:

    let strings = ["foobar", "Hello (45.5 km)", "George St. (39.5 km)", "Salut (20.45 km)", "Bonjour (30 km)", "Hi (35 km)"]
    
    let stringsWithNumbers = strings.flatMap {str in
    
        // trim away the non numerical characters, and attempt to create a double from the result
        Double(str.stringByTrimmingCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet)).map {(string: str, number: $0)}
    }
    
    print(stringsWithNumbers) // [("Hello (45.5 km)", 45.5), ("George St. (39.5 km)", 39.5), ("Salut (20.45 km)", 20.449999999999999), ("Bonjour (30 km)", 30.0), ("Hi (35 km)", 35.0)]
    

    请注意,这不适用于包含多个数字的字符串(尽管我想不出你会如何处理这种情况)。

    如果你知道你的距离总是包含在圆括号中,你可以添加一些额外的代码来允许括号之外的数字,首先将字符串修剪到括号,然后修剪到数字。例如:

    let strings = ["foobar", "5th Avenue (3 km)", "Hello (45.5 km)", "George St. (39.5 km)", "Salut (20.45 km)", "Bonjour (30 km)", "Hi (35 km)"]
    
    let stringsWithNumbers:[(string:String, number:Double)] = strings.flatMap{str in
    
        // the substring of the brackets
        let brackets = str.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "()").invertedSet)
    
        // the number within the brackets
        let num = brackets.stringByTrimmingCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet)
    
        // attempt to create a double from the result
        return Double(num).map {(string: str, number: $0)}
    }
    
    print(stringsWithNumbers) // [("5th Avenue (3 km)", 3.0), ("Hello (45.5 km)", 45.5), ("George St. (39.5 km)", 39.5), ("Salut (20.45 km)", 20.449999999999999), ("Bonjour (30 km)", 30.0), ("Hi (35 km)", 35.0)]
    

    然后您可以使用sort 函数对该数组进行排序。例如:

    let sorted = stringsWithNumbers.sort {$0.number < $1.number}.map{$0.string} // sort, then ditch the distance information
    print(sorted) // ["5th Avenue (3 km)", "Salut (20.45 km)", "Bonjour (30 km)", "Hi (35 km)", "George St. (39.5 km)", "Hello (45.5 km)"]
    

    如果您希望保留双精度字符串的元组,您可以删除末尾的 map

    【讨论】:

    • 您好!你的答案有效!但不是全部...我有例如:333.1、384.1、239.1 和 0.0。您的代码给了我这个命令:0.0、384.1、239.1 和 333.1 我该怎么做?
    • @L.Verardo 嗯,你从来没有说过你需要处理非整数;)我会用更通用的方法更新我的答案,当我得到一个可以处理带小数点的数字时时刻。
    • 非常感谢! :)
    • 你能告诉我你知道什么时候可以编辑吗?所以我知道什么时候可以回来查看:)
    • @sketchyTech 我已经更新了我的答案来处理这种情况。您可能是正确的,正则表达式是要走的路——完全取决于 OP 的输入的可预测性。
    【解决方案3】:

    假设您从某个外部来源接收此类输入,您不必以数字​​作为单独的字段开头,您需要将要排序的组件(数字)提取为某种表示形式在其中将要排序的组件映射到原始字符串(也可以使用字典来完成,就像在其他建议的解决方案之一中一样,然后将排序后的数字字符串关联数组映射到您想要排序的字符串第三步。

    我下面的解决方案有点冗长,但它向您展示了如何从字符串中提取数字,并处理错误的输入(“你好”,它根本不包括数字部分,被排序最后——你也可以很容易地过滤掉它,因为distance 组件被建模为一个可选组件,并且不遵循该模式的情况具有此值作为nil)。

    import Foundation
    
    let arrayEntr = ["Hello (40 km)", "Salut (20 km)", "Bonjour (30 km)", "Hi (35 km)", "Hi there"]
    
    let expr = try! NSRegularExpression(pattern: "\\((\\d+)", options: [])
    
    typealias MatchTuple = (string:String, distance:Int?)
    
    // 1. Extract the numbers out, and take into account possible bad input.
    let matches = arrayEntr.map { str -> MatchTuple in
        let range = expr.matchesInString(str, options: [], range: NSMakeRange(0, str.utf8.count)).first?.rangeAtIndex(1)
    
        let match:String?
        if let range = range {
            match = (str as NSString).substringWithRange(range)
        }
        else {
            match = nil
        }
    
        let distance:Int?
        if let match = match {
            distance = Int(match)
        }
        else {
            distance = nil
        }
    
        return (string:str, distance:distance)
    }
    
    // 2. Sort the tuples of string / number combinations. 
    let sortedMatches = matches.sort { a, b in
        if let aDist = a.distance, let bDist = b.distance {
            return aDist < bDist
        }
    
        if a.distance == nil && b.distance == nil {
            return a.string.compare(b.string) == .OrderedAscending
        }
    
        if a.distance != nil && b.distance == nil {
            return true
        }
    
        return false
    }
    
    3. Map the string, number tuples into just the string.
    print(sortedMatches.map { $0.string })
    

    【讨论】:

      【解决方案4】:

      创建一个类似的字典

      let dictionary = [ "40" : "Hello (40 km)", "20" : "Salut (20 km)", "30" : "Bonjour (30 km)", "35" : "Hi (35 km)", ]

      并按如下方式对该字典进行排序:

      如果您只想要密钥:let sortedKeys = Array(dictionary.keys).sorted(&lt;) // ["20", "30", "35", "40"]

      如果您想要排序的键和值:let sortedKeysAndValues = sorted(dictionary) { $0.0 &lt; $1.0 } // Resulted ArrayList [("20", "Salut (20 km)"), ("30", "Bonjour (30 km)"), ("35", "Hi (35 km)"), ("40", "Hello (40 km)")]

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-02-18
        • 2016-12-07
        • 1970-01-01
        • 1970-01-01
        • 2015-07-07
        • 1970-01-01
        相关资源
        最近更新 更多