使用Swift对数组进行升序排列,其中包含空项。

7

在Xcode(Swift)中,我有一个数组,它被初始化为100个空项:

var persons = [String](count:100, repeatedValue: "")

使用一些函数,我可以将内容添加到数组中的某些位置,从0开始。

所以例如,在某个时刻我的数组可能是这样的:

["Bert", "Daniel", "Claire", "Aaron", "", "", ... ""]

这段代码用于将数组按字母顺序排序,其中空项由点号表示:

persons = persons.sorted {$0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }

这会给我返回这样的一组数组:
["", "", ... , "Aaron", "Bert", "Claire", "Daniel"]

我想对我的数组进行字母顺序排序,但不需要将空元素排在前面。我需要得到如下的数组:
["Aaron", "Bert", "Claire", "Daniel", "", "", ... , ""]

就我个人而言,我不想要含有空项的数组,但是我发现如果我不像声明一个100项的数组,我就无法向其中添加值(这个数组肯定不会填满100项)。

有人能帮帮我吗?


1
不确定你所说的"I found I couldn't add a value to my array if I did not declare like a 100 items"的意思。是否指无法向数组中追加元素? - Antonio
而且你的代码按降序对元素进行排序(正如标题中所提到的)。这将把空字符串放在最后。你的示例输出与代码不匹配。 - Martin R
@Antonio 不,我想要的是一个可以添加和删除值的数组。理想情况下,这个数组只包含值而不包含空项,因此它在任何时候都只需要足够长。如果我需要添加一个值,我会需要一个新项目来扩展数组。我只是选择给了它100个带有值“”的项目,所以我总是有空间来添加一个新的值。你知道我的意思吗? - B_s
@MartinR 是的,你说得对。我复制了错误的部分,抱歉。我已经更新了原帖。 - B_s
3个回答

10

正如@Antonio所说,看起来你需要一个字符串的降序集合。除了@Antonio答案中的Dictionary方法(非常有效),你还可以使用NSMutableSet(从Objective-C桥接而来):

let personSet = NSMutableSet()
personSet.addObject("Aaron")
personSet.addObject("Daniel")
personSet.addObject("Claire")
personSet.addObject("Aaron")
personSet.addObject("Bert")
personSet.addObject("Bert")
personSet.addObject("Joe")
personSet.removeObject("Joe") // You can remove too of course

这将创建一个集合:

{(
    Claire,
    Aaron,
    Daniel,
    Bert
)}

然后,当你想把人们作为一个 Array 时,可以使用 allObjects 转换为 [String]:

personSet.allObjects as [String]

您可以像目前所做的那样对其进行排序:

let people = (personSet.allObjects as [String]).sort {$0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }

这使得人们

[Aaron, Bert, Claire, Daniel]

对于那些想知道如何按照问题中所述的方式(升序,但空字符串排在最后)对Array进行排序的人,可以在排序函数中使用一些自定义逻辑来实现:
var persons = ["Bert", "Daniel", "Claire", "Aaron", "", "", ""]
persons.sort { (a, b) -> Bool in
    if a.isEmpty {
        return false
    } else if b.isEmpty {
        return true
    } else {
        return a.localizedCaseInsensitiveCompare(b) == .OrderedAscending
    }
}

结果:

["Aaron", "Bert", "Claire", "Daniel", "", "", ""]

谢谢。对于将数组按升序排序并将空项放在末尾的最后一部分确实解决了我的问题,这就是我选择它作为解决方案的原因。感谢大家(特别是@Antonio)提供的其他选项和文档! - B_s
@Bastiaan 不用谢。但是,根据你的需求,我强烈建议使用 @Antonio 的 Dictionary 方法或 NSMutableSet,而不是预先用空字符串填充一个 Array;这样会更有效率。 - Mike S
我理解了,一定会尝试将我的程序转换为使用像Antonio或你的NSMutableSet建议中的字典。 - B_s

2

根据您提出问题和其他答案中的评论,我意识到您需要一个有序集合,其中包含唯一的值。在 Swift 中没有内置的数据结构来实现这一点,但可以通过使用字典轻松完成:只需将字符串值用作字典键,布尔值用作字典值-这样可以确保键是唯一的:

var persons = [String : Bool]()

persons["Bert"] = true
persons["Daniel"] = true
persons["Clair"] = true
persons["Clair"] = true
persons["Aaron"] = true
persons["Daniel"] = true
persons["Clair"] = true

您可以快速验证上述代码中字典仅包含4个元素。

接下来,获取字典键的副本(作为数组):

var values = persons.keys.array

并对其进行排序:

values.sort { $0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }

或者,如果您想继续使用固定大小的数组,可以在排序之前删除空项:

persons = persons
            .filter( { $0.isEmpty == false } )
            .sorted {$0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }

是的,但我仍然需要将新人添加到数据库中。 - B_s
我不明白问题出在哪里。 persons["Clair"] = true 又出了什么问题? - Antonio
用户例如输入一个新的名字“Pete”,这也需要被存储。如果我没有理解您的意思,那是因为字典的整个概念对我来说是新的,我仍在学习Swift... - B_s
1
如果你想有效地开发Swift,我建议你多了解一下字典。顺便说一句,我已经更新了我的回答,快来看看吧。 - Antonio
1
@Bastiaan persons["Pete"] = truePete 添加到 Dictionarypersons["Pete"] = nilDictionary 中删除它。使用这些方法,您可以添加和删除任何需要的项。 - Mike S
显示剩余3条评论

2

我认为你对数组有些困惑。Swift 数组不是必须分配并填充到最大设计容量的静态分配结构。下面是一个简单的示例,展示了如何实现你所表达的大部分内容。然而,我真的认为字典更适合你的需求。

var persons = [String]()
var inputData = ["Bert", "Daniel", "Bert", "Claire", "Aaron"]
for item in inputData {
    var found = false
    for existing in persons {
        if existing == item {
            found = true
            break
        }
    }
    if (!found) {
         persons.append(item)
    }
}
persons.sort{$0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }
println(persons)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接