Sorting 如何按多个条件对Swift对象进行排序
我有一个Swift对象列表,我想按多个条件进行排序。列表中的对象类型为Sorting 如何按多个条件对Swift对象进行排序,sorting,swift,Sorting,Swift,我有一个Swift对象列表,我想按多个条件进行排序。列表中的对象类型为DateRange: class DateRange { var from: NSDate? var to: NSDate? } 该列表包含许多这样的对象,其中一些from或to字段为零。我希望此列表按以下顺序排序: 首先是所有有日期的对象 然后是至少有一个日期的对象(从到或到) 在最末端,没有任何物体 日期本身并不重要,只是它们的存在。在Ruby中,我可以这样做(如果日期是nil我将其设置为非常低的日期):
DateRange
:
class DateRange {
var from: NSDate?
var to: NSDate?
}
该列表包含许多这样的对象,其中一些from
或to
字段为零。我希望此列表按以下顺序排序:
nil
我将其设置为非常低的日期):
date_ranges.sort{a,b|
[固定零(a.from),固定零(a.to)][固定零(b.from),固定零(b.to)]
}.反向
def fix_nil(val)
val.nil?新日期(0):val
结束
用斯威夫特做这件事最好的方法是什么?提前谢谢。我想你所说的列表是指数组,所以我的回答基于这个假设
您可以使用数组结构的sort
方法,该方法接受具有以下签名的闭包:
(lhs: T, rhs: T) -> Bool
如果lhs
小于rhs
,则返回true
,否则返回false
我提出了这个实现:
var x: [DateRange]
// ... initialize the array
x.sort { (lhs: DateRange, rhs: DateRange) -> Bool in
if lhs.from != nil && lhs.to != nil {
return true
}
if lhs.from == nil && lhs.to == nil {
return false
}
return rhs.from == nil && rhs.to == nil
}
- 如果
两个属性都不是nil,那么不管lhs
rhs
- 如果
同时具有两个属性nil,则无论lhs
rhs
- else
有一个nil,另一个不是nil,在这种情况下,只有当lhs
两个属性都为nil时,它才排在第一位rhs
排序
,最好将代码移出排序
方法-最好的地方可能是
操作符的重载:/p
预失效<(左:日期范围,右:日期范围)->Bool{
如果lhs.from!=nil&&lhs.to!=nil{
返回真值
}
如果lhs.from==nil&&lhs.to==nil{
返回错误
}
返回rhs.from==nil&&rhs.to==nil
}
在这种情况下,可按如下方式使用:
x.sort(<)
x.sort(以下是我的方法。为了保持简单,请为日期范围添加评分函数。在您的场景中,有3种可能性:
零分&零分:0分
无和日期:1分
日期和日期:2分
import Foundation
class DateRange {
var from: NSDate?
var to: NSDate?
init(from: NSDate?, to: NSDate?)
{
self.from = from
self.to = to
}
func scoreDateRange() -> Int
{
var score = 0
if from != nil
{
score++
}
if to != nil
{
score++
}
return score
}
}
func sortDateRange( d1 : DateRange, d2 : DateRange)-> Bool
{
return d1.scoreDateRange() > d2.scoreDateRange()
}
var date_ranges = [DateRange]()
date_ranges.append(DateRange(from:nil, to:nil))
date_ranges.append(DateRange(from:nil, to:nil))
date_ranges.append(DateRange(from:NSDate(), to:NSDate()))
date_ranges.append(DateRange(from:nil, to:NSDate()))
date_ranges.append(DateRange(from:NSDate(), to:nil))
date_ranges.append(DateRange(from:NSDate(), to:NSDate()))
date_ranges.sort(sortDateRange)
似乎最好将dateCount
computed属性添加到DateRange
类型中。这将是进行模式匹配的好时机:
extension DateRange {
// returns the number of non-nil NSDate members in 'from' and 'to'
var dateCount: Int {
switch (from, to) {
case (nil, nil): return 0
case (nil, _): return 1
case (_, nil): return 1
default: return 2
}
}
}
然后,您可以使用简单的闭包对列表进行排序:
var ranges = [DateRange(nil, nil), DateRange(NSDate(), nil), DateRange(nil, NSDate()), DateRange(nil, nil), DateRange(NSDate(), NSDate())]
ranges.sort { $0.dateCount > $1.dateCount }
如果您愿意,您甚至可以通过增加几行代码使其具有可比性:
extension DateRange : Comparable { }
func ==(lhs: DateRange, rhs: DateRange) -> Bool {
return lhs.dateCount == rhs.dateCount
}
func <(lhs: DateRange, rhs: DateRange) -> Bool {
return lhs.dateCount > rhs.dateCount
}
扩展日期范围:可比较{}
func==(左:日期范围,右:日期范围)->Bool{
返回lhs.dateCount==rhs.dateCount
}
func Bool{
返回lhs.dateCount>rhs.dateCount
}
这使您可以使用运算符参数对列表进行正确排序:
ranges.sort(<)
ranges.sort(我认为您的比较有一个bug——当比较两个相同的DateRange
实例时,如果它们都是(nil,nil),这将返回true)
。第二个if应该包括这一点:如果lhs都为nil,它返回false对不起——我倒过来了。如果两个范围都有两个日期,这将返回true,因为第一个条件只是查看lhs
。感谢您的回答,特别是“就地”排序的提示。我现在使用sortBy
函数ich可以很好地处理不可变的数据。评分功能的好主意,谢谢你的快速回答!
extension DateRange : Comparable { }
func ==(lhs: DateRange, rhs: DateRange) -> Bool {
return lhs.dateCount == rhs.dateCount
}
func <(lhs: DateRange, rhs: DateRange) -> Bool {
return lhs.dateCount > rhs.dateCount
}
ranges.sort(<)