我的问题很简单:
如果用户完成锻炼,他将输入时间,否则,他将输入数字或重复次数。
为简单起见,结果对象如下:
Result |_ resultValue (Int) // It can be time in seconds or number of reps |_ isFinished (Int) // It can be 0 (not finished) or 1 (finished)
我想对结果数组进行如下排序:
- 首先:isFinished == 1的所有结果均高于其他结果
- 然后:按resultValue DESC对isFinished == 1的结果进行排序
- 最后:按resultValue ASC对isFinished == 0的结果进行排序
我尝试过类似的事情:
self.results = self.results.sorted {
($0.result.isForTimeFinished!, $0.result.resultValue!) >
($1.result.isForTimeFinished!, $1.result.resultValue!)
}
因此,锻炼结果尚未完成是在锻炼结果之后,但是“按resultValue DESC对isFinished == 1的结果进行排序”是不行的...
您知道我如何将所有这些结合起来吗?
答案 0 :(得分:1)
尝试一下:
self.results = self.results.sorted {
if $0.result.isForTimeFinished != $1.result.isForTimeFinished {
return $0.result.isForTimeFinished > $1.result.isForTimeFinished
}
else if $0.result.isForTimeFinished == 0 {
return $0.result.resultValue > $1.result.resultValue
}
else {
return $0.result.resultValue < $1.result.resultValue
}
}
注意:我可能有相反的迹象,但有点儿玩
答案 1 :(得分:1)
逻辑OR
在第一个TRUE
评估时停止,因此无需评估下一个表达式。当列表中$0
应该位于$1
上方时,有3条规则,请尝试下一个:
self.results = self.results.sorted {
let b0 = $0.result.isForTimeFinished!
let b1 = $1.result.isForTimeFinished!
let v0 = $0.result.resultValue!
let v1 = $1.result.resultValue!
// $0 will be above $1 in the list if returning true, otherwise it will be listed lower
return
b0 && !b1 // is finished > not finished
||
b0 && b0 == b1 && v0 < v1 // both finished, higher value
||
!b0 && b0 == b1 && v0 > v1 // both not finished, lower value
}
答案 2 :(得分:0)
我个人会在您的结果模型中添加一个经过计算的var
,称为searchScore
之类的东西,但是可以进行计算(尽管我并未完全遵循您的目标,但看起来基本上打破了您的目标数据分成3个层,然后按升/降顺序进行操作),然后就可以对它进行简单的排序了。
像这样
class Result {
...
var searchScore: Double {
return *ALGORITHM FOR SCORE*
}
}
let sorted = results.sorted {$0.searchScore < $0.searchScore}
这种方法的真正好处是可以使您的代码更整洁,而不必在如何在错误的位置订购事物方面有真正的复杂性。