通过带有条件的自定义属性和其次自定义属性desc来命令swift数组

时间:2017-05-19 15:45:58

标签: arrays swift

我有一个自定义对象的数组。该对象包含属性endDate。

我需要能够以类似于下面的sql:

的方式对我的数组进行排序
order by enddate = 0 desc, enddate desc

我知道如何做第二部分:

arr.sorted(by : {$0.enddate > $1.enddate})

但我不知道如何通过有条件的enddate排序

输入

[{x: "blah", enddate : 123456}, {x: "blah2", enddate : 234567}, {x: "blah3", enddate : 345678}, {x: "blah4", enddate : 0}]

所以我希望输出让enddate降序,除非enddate是0,例如0, 345678, 234567, 123456

2 个答案:

答案 0 :(得分:1)

在实现这些类型的自定义排序顺序时,您应该记住传递给sorted(by:)的排序谓词的语义要求。这些要求列于in the documentation

  

谓词必须是元素上的严格弱排序。那   是,对于任何元素a,b和c,必须满足以下条件:

     
      
  • areInIncreasingOrder(a, a)始终为false。 (Irreflexivity)
  •   
  • 如果areInIncreasingOrder(a, b)areInIncreasingOrder(b, c)都是true,那么areInIncreasingOrder(a, c)也是true。 (传递   可比性)
  •   
  • 如果两个元素都不是根据谓词在另一个元素之前排序,则无法比较。如果a和b是无与伦比的,那么b和c   是无与伦比的,那么a和c也是无与伦比的。 (传递   不可比性)
  •   

不遵守这些要求可能会导致数组排序错误。因此,考虑到这些要求,这是表达排序顺序的一种方式:

struct S {
    var endDate: Int
}

let arr = [S(endDate: 123456), S(endDate: 234567), S(endDate: 345678), S(endDate: 0)]

let result = arr.sorted {
    switch ($0.endDate, $1.endDate) {
    case (_, 0):
        return false
    case (0, _):
        return true
    case let (lhs, rhs):
        return lhs > rhs
    }
}

print(result)
// [S(endDate: 0), S(endDate: 345678), S(endDate: 234567), S(endDate: 123456)]

我们在这里使用的排序谓词是:

  • 反身:(0, 0)是假的。其他(a, a)其中a != 0也是假的,因为>也是不自反的。
  • 可传比较可比:(0, a)其中a != 0为真,(a, 0)为假。由>处理的任何其他组合,具有可传递性的可比性。
  • 传递无法比较:对于包含至少一个0的给定对,另一个元素必须是0才能无法比拟。因此,a == b == c == 0(a, c)确实无法比拟。由>处理的任何其他组合,它具有传递性,无法比拟。

答案 1 :(得分:-1)

试试这个:

var sorted = data.sorted { $0.enddate == 0 ? true : $0.enddate > $1.enddate }