Swift - 通过多次比较对数组进行排序
Swift - Sort Array with several comparison
我的问题很简单:
- 我的数据库中有很多用户评分(顺便说一句,我正在使用 Firebase)
- 我想得到这些分数(这很容易)并对它们进行排序(不太容易)
如果用户完成锻炼,他将输入他的时间,如果没有,他将输入次数或重复次数。
为了简单起见,结果对象是这样的:
Result
|_ resultValue (Int) // It can be time in seconds or number of reps
|_ isFinished (Int) // It can be 0 (not finished) or 1 (finished)
我想像这样对结果数组进行排序:
- First: All results with isFinished == 1 are higher than the others
- Then: Sort results where isFinished == 1 by resultValue DESC
- Finally: Sort results where isFinished == 0 by resultValue ASC
我试过类似的东西:
self.results = self.results.sorted {
([=12=].result.isForTimeFinished!, [=12=].result.resultValue!) >
(.result.isForTimeFinished!, .result.resultValue!)
}
所以未完成锻炼的结果是锻炼完成后的结果,但是 "Sort results where isFinished == 1 by resultValue DESC" 不行...
你知道我如何将所有这些结合起来吗?
我个人会在你的结果模型中添加一个计算的 var
,称为 searchScore
之类的东西,它会被计算(虽然我没有完全遵循你的目标,但它看起来基本上将您的数据分成 3 层,然后使用 ascending/descending),然后您可以对其进行简单排序。
所以像这样
class Result {
...
var searchScore: Double {
return *ALGORITHM FOR SCORE*
}
}
let sorted = results.sorted {[=10=].searchScore < [=10=].searchScore}
这种方法的真正优点是让您的代码更简洁,而不必在错误的地方排序的问题变得非常复杂。
试试这个:
self.results = self.results.sorted {
if [=10=].result.isForTimeFinished != .result.isForTimeFinished {
return [=10=].result.isForTimeFinished > .result.isForTimeFinished
}
else if [=10=].result.isForTimeFinished == 0 {
return [=10=].result.resultValue > .result.resultValue
}
else {
return [=10=].result.resultValue < .result.resultValue
}
}
注意:我可能把标志弄反了,但还是玩了一下
逻辑 OR
首先停止 TRUE
计算,因此不需要计算下一个表达式。当 [=13=]
应该在列表中的 </code> 之上时有 3 条规则,尝试下一个:</p>
<pre><code>self.results = self.results.sorted {
let b0 = [=10=].result.isForTimeFinished!
let b1 = .result.isForTimeFinished!
let v0 = [=10=].result.resultValue!
let v1 = .result.resultValue!
// [=10=] will be above 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
}
我的问题很简单:
- 我的数据库中有很多用户评分(顺便说一句,我正在使用 Firebase)
- 我想得到这些分数(这很容易)并对它们进行排序(不太容易)
如果用户完成锻炼,他将输入他的时间,如果没有,他将输入次数或重复次数。
为了简单起见,结果对象是这样的:
Result |_ resultValue (Int) // It can be time in seconds or number of reps |_ isFinished (Int) // It can be 0 (not finished) or 1 (finished)
我想像这样对结果数组进行排序:
- First: All results with isFinished == 1 are higher than the others
- Then: Sort results where isFinished == 1 by resultValue DESC
- Finally: Sort results where isFinished == 0 by resultValue ASC
我试过类似的东西:
self.results = self.results.sorted {
([=12=].result.isForTimeFinished!, [=12=].result.resultValue!) >
(.result.isForTimeFinished!, .result.resultValue!)
}
所以未完成锻炼的结果是锻炼完成后的结果,但是 "Sort results where isFinished == 1 by resultValue DESC" 不行...
你知道我如何将所有这些结合起来吗?
我个人会在你的结果模型中添加一个计算的 var
,称为 searchScore
之类的东西,它会被计算(虽然我没有完全遵循你的目标,但它看起来基本上将您的数据分成 3 层,然后使用 ascending/descending),然后您可以对其进行简单排序。
所以像这样
class Result {
...
var searchScore: Double {
return *ALGORITHM FOR SCORE*
}
}
let sorted = results.sorted {[=10=].searchScore < [=10=].searchScore}
这种方法的真正优点是让您的代码更简洁,而不必在错误的地方排序的问题变得非常复杂。
试试这个:
self.results = self.results.sorted {
if [=10=].result.isForTimeFinished != .result.isForTimeFinished {
return [=10=].result.isForTimeFinished > .result.isForTimeFinished
}
else if [=10=].result.isForTimeFinished == 0 {
return [=10=].result.resultValue > .result.resultValue
}
else {
return [=10=].result.resultValue < .result.resultValue
}
}
注意:我可能把标志弄反了,但还是玩了一下
逻辑 OR
首先停止 TRUE
计算,因此不需要计算下一个表达式。当 [=13=]
应该在列表中的 </code> 之上时有 3 条规则,尝试下一个:</p>
<pre><code>self.results = self.results.sorted {
let b0 = [=10=].result.isForTimeFinished!
let b1 = .result.isForTimeFinished!
let v0 = [=10=].result.resultValue!
let v1 = .result.resultValue!
// [=10=] will be above 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
}