我如何根据以下需求对NSArray进行排序/过滤?

时间:2015-04-16 09:07:32

标签: ios arrays swift sorting filtering

有人可以告诉我一种以正确的方式过滤/排序我的阵列的方法吗?

我目前拥有的Playground如下:

//: Playground - noun: a place where people can play

import UIKit

var candidates: NSArray = ["Berlin-Lichtenberg", "Berlin-Lichterfelde Ost", "Berlin-Lichterfelde West", "Braunsdorf-Lichtenwalde", "Darmstadt-Lichtwiese", "Lichtenberg (Erzgeb)", "Lichtenfels", "Lichtenrade", "Lichtenstein (Sachs)", "Lichtentanne (Sachs)", "Lichtentanne (Thür)", "Lichtenthal", "Lichterfelde Süd", "Rostock Lichtenhagen", "Hamburg", "München", "Köln", "Bonn"]

var root = "Licht"

var predicate = NSPredicate(format: "(SELF BEGINSWITH[c] %@) OR (SELF MATCHES[c] %@)", root, NSString(format: ".*[^\\w]%@.*", root))

var filteredArray = NSMutableArray(array: candidates.filteredArrayUsingPredicate(predicate))

println(filteredArray)

这将打印出以下内容:

(
"Berlin-Lichtenberg",
"Berlin-Lichterfelde Ost",
"Berlin-Lichterfelde West",
"Braunsdorf-Lichtenwalde",
"Darmstadt-Lichtwiese",
"Lichtenberg (Erzgeb)",
Lichtenfels,
Lichtenrade,
"Lichtenstein (Sachs)",
"Lichtentanne (Sachs)",
"Lichtentanne (Thu\U0308r)",
Lichtenthal,
"Lichterfelde Su\U0308d",
"Rostock Lichtenhagen"
}

这一切都运行正常,但我需要的数组的排序是另一个,我不能正确:(

这是它的样子:

(
"Lichtenberg (Erzgeb)",
Lichtenfels,
Lichtenrade,
"Lichtenstein (Sachs)",
"Lichtentanne (Sachs)",
"Lichtentanne (Thu\U0308r)",
Lichtenthal,
"Lichterfelde Su\U0308d",
"Berlin-Lichtenberg",
"Berlin-Lichterfelde Ost",
"Berlin-Lichterfelde West",
"Braunsdorf-Lichtenwalde",
"Darmstadt-Lichtwiese",
"Rostock Lichtenhagen"
)

所以我需要的结果以我的搜索字符串(root)开头,这是“Licht”开头的,然后它应该显示其中只包含它的其他字符。

我怎么能够实现这个目标?

2 个答案:

答案 0 :(得分:4)

我建议使用Swift数组类型而不是NSArray,并使用filter结合sort方法,该方法采用闭包来确定2个元素的排序顺序。

在您的情况下,它将实现为:

var candidates = ["Berlin-Lichtenberg", "Berlin-Lichterfelde Ost", "Berlin-Lichterfelde West", "Braunsdorf-Lichtenwalde", "Darmstadt-Lichtwiese", "Lichtenberg (Erzgeb)", "Lichtenfels", "Lichtenrade", "Lichtenstein (Sachs)", "Lichtentanne (Sachs)", "Lichtentanne (Thür)", "Lichtenthal", "Lichterfelde Süd", "Rostock Lichtenhagen", "Hamburg", "München", "Köln", "Bonn"]

let root = "Licht"

var results = candidates.filter {
    $0.rangeOfString(root) != nil
}.sorted { (lhs: String, rhs: String) -> Bool in
    if startsWith(lhs, root) {
        if (startsWith(rhs, root)) {
            // Both start with root, so return the string comparison
            return lhs < rhs
        }
        // lhs starts with root, rhs doesn't, so lhs comes first
        return true
    }

    // rhs starts with root, lhs doesn't, so rhs comes first
    if (startsWith(rhs, root)) {
        return false
    }

    // return the normal string comparison
    return lhs < rhs
}

答案 1 :(得分:2)

let candidates: [String] = ["Berlin-Lichtenberg", "Berlin-Lichterfelde Ost", "Berlin-Lichterfelde West", "Braunsdorf-Lichtenwalde", "Darmstadt-Lichtwiese", "Lichtenberg (Erzgeb)", "Lichtenfels", "Lichtenrade", "Lichtenstein (Sachs)", "Lichtentanne (Sachs)", "Lichtentanne (Thür)", "Lichtenthal", "Lichterfelde Süd", "Rostock Lichtenhagen", "Hamburg", "München", "Köln", "Bonn"].sorted{$0 < $1}

let root = "Licht"

var filtered: [String] = []

filtered += candidates.filter{$0.hasPrefix(root)}
filtered += candidates.filter{$0.hasPrefix(root) == false && $0.rangeOfString(root, options: nil) != nil}

println(filtered) // "[Lichtenberg (Erzgeb), Lichtenfels, Lichtenrade, Lichtenstein (Sachs), Lichtentanne (Sachs), Lichtentanne (Thür), Lichtenthal, Lichterfelde Süd, Berlin-Lichtenberg, Berlin-Lichterfelde Ost, Berlin-Lichterfelde West, Braunsdorf-Lichtenwalde, Darmstadt-Lichtwiese, Rostock Lichtenhagen]"