我有一个Swift对象列表,我希望按多个条件对其进行排序。列表中的对象类型为DateRange
:
class DateRange {
var from: NSDate?
var to: NSDate?
}
该列表包含许多这些对象,其中一些from
或to
字段为零。我希望将此列表排序依据:
from
或to
)日期本身并不重要,只是它们的存在。在Ruby中我可以这样做(如果日期是nil
我将它设置为一个非常低的日期):
date_ranges.sort { |a, b|
[fix_nil(a.from), fix_nil(a.to)] <=> [fix_nil(b.from), fix_nil(b.to)]
}.reverse
def fix_nil(val)
val.nil? ? Date.new(0) : val
end
使用Swift执行此操作的最佳方法是什么?提前谢谢。
答案 0 :(得分:2)
似乎将dateCount
计算属性添加到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 }
如果您愿意,您甚至可以使用更多行来Comparable
:
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(<)
答案 1 :(得分:1)
我认为 list 是指 array ,所以我的答案基于这个假设。
您可以使用数组结构的sort
方法,该方法采用具有此签名的闭包:
(lhs: T, rhs: T) -> Bool
如果true
小于lhs
,则返回rhs
,否则返回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
}
lhs
两个属性都不是nil,则无论rhs
lhs
的属性均为nil,则无论rhs
lhs
只有一个nil,另一个不是nil,在这种情况下,只有当rhs
具有两个属性nil时它才会出现如果您计划在多个地方重复使用sort
,最好将代码移出sort
方法 - 最佳位置可能是<
运算符的重载:
func < (lhs: DateRange, rhs: DateRange) -> Bool {
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
}
在这种情况下,可以按如下方式使用:
x.sort(<)
如果您不喜欢运算符重载,您当然可以为该函数指定任何其他名称。
请注意,排序是到位。
答案 2 :(得分:1)
以下是我将如何处理这个问题。为简单起见,请为日期范围添加评分函数。在您的方案中,您有3种可能性:
nil&amp;零:0分
nil&amp;日期:1分
日期&amp;日期: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)