如何在Swift中对带有字符串的数组进行排序?

时间:2016-05-01 21:18:58

标签: ios arrays swift sorting

我有这些数组:

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

我想以与ArraySorted相同的顺序替换ArrayEntr。事实上,我想用最后的数字对ArrayEntr进行排序

我尝试了几个循环,但我无法按照自己的意愿运行。

非常感谢!

4 个答案:

答案 0 :(得分:3)

因为你知道你需要这样做,所以提前计划;将原始数组形成为string-Int元组的数组:

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

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

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

答案 1 :(得分:0)

创建一个像

这样的字典

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

并将此词典排序如下:

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

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

答案 2 :(得分:0)

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

我的解决方案有点冗长,但它向您展示了如何从字符串中提取数字,并处理错误的输入(“Hi there”,根本不包括数字组件,将被排序最后 - 如果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 })

答案 3 :(得分:0)

如果您从外部来源获取此数组并且不提供数字信息以及字符串,则您必须自己从中提取数字。当然,如果您在某些时候开始提供数字信息,那么您应该将其挂在@matt says上。

从数组中获取数字信息的一种方法是在数组上使用flatMap,然后使用stringByTrimmingCharactersInSet以便从字符串的每一端修剪掉非数字字符。然后,您可以尝试创建一个双精度数组,以便创建一个新的(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