繁体   English   中英

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

[英]How to sort an array with string in it in Swift?

我有这些数组:

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

我想以与ArraySorted相同的顺序替换ArrayEntr。 实际上,我想对ArrayEntr进行升序排序,并在末尾加上数字

我已经尝试了一些循环,但是我无法按照我的意愿使其工作。

非常感谢 !

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

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

现在,问题变得微不足道了:只需对每种类型的第二个成员进行排序,即$0.1

如果您不这样做,则将不得不以某种方式找到每个字符串中埋藏的数字。 您可以这样做,但是大概在某个时候有一个数字,因此将其埋入字符串中似乎很愚蠢,以至于很难再次将其收回。

创建一个类似的字典

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)")]

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

我下面的解决方案有些冗长,但是它向您展示了如何从字符串中提取数字,并处理了错误的输入(“ 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 })

如果要从不提供数字信息和字符串的外部源获取此数组,则必须自己从中提取数字。 当然,如果您从某个时候开始就拥有数字信息,则应该像@matt所说的那样挂在上面

从字符串中获取数字信息的一种方法是在数组上使用flatMap ,然后使用stringByTrimmingCharactersInSet以便从字符串的每一端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函数对该数组进行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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM