按两个属性对对象数组进行排序

33

之前已经有人用 NSSortDescriptor 提出并回答了这个问题,使用它非常简单。但是是否有一种符合 Swift 标准的方法可以使用 Array.sort()

struct Sortable {
    let isPriority: Bool
    let ordering: Int
}

按照一个属性对一个 Sortables 数组进行排序是很简单的:

sort { $0.ordering < $1.ordering }

但是我想按isPriority然后按ordering排序——我无法理解一个简单的语句来实现这个功能。


我们应该将这个问题标记为重复,并指向更受欢迎的变体吗?https://stackoverflow.com/q/37603960/3141234 - undefined
4个回答

64

使用 Array.sort() 很容易实现。

代码:

var sorted = array.sorted({ (s1, s2) -> Bool in
    if s1.isPriority && !s2.isPriority {
        return true //this will return true: s1 is priority, s2 is not
    }
    if !s1.isPriority && s2.isPriority {
        return false //this will return false: s2 is priority, s1 is not
    }
    if s1.isPriority == s2.isPriority {
        return s1.ordering < s2.ordering //if both save the same priority, then return depending on the ordering value
    }
    return false
})

已排序的数组:

true - 10
true - 10
true - 12
true - 12
true - 19
true - 29
false - 16
false - 17
false - 17
false - 17
false - 18

另一种稍微更短的解决方案:

let sorted = array.sorted { t1, t2 in 
   if t1.isPriority == t2.isPriority {
      return t1.ordering < t2.ordering 
   }
   return t1.isPriority && !t2.isPriority 
}

这非常好,谢谢。可以更简洁地写 - 我会在你的答案中添加。 - tobygriffin
6
我的编辑被拒绝了,所以这里是我使用的代码。let sorted = array.sorted { t1, t2 in if t1.isPriority == t2.isPriority { return t1.ordering < t2.ordering } return t1.isPriority && !t2.isPriority } - tobygriffin
@Crashalot 是的。但在旧版Swift中,它是'.sorted'。 - Dejan Skledar
@DejanSkledar 的意见很有道理,但是也许需要对新的 Swift 用户进行编辑? - Crashalot
完全同意你的观点。如果有修改建议,我也不介意,因为在回答很多问题后,你可能会落后于更新它们。 - Dejan Skledar
显示剩余2条评论

17

这里有一个简单的语句来进行排序:

var sorted = array.sort { $0.isPriority == $1.isPriority ? $0.ordering < $1.ordering : $0.isPriority && !$1.isPriority }

2
符合 Comparable 接口!
extension Sortable: Comparable {
  static func < (sortable0: Sortable, sortable1: Sortable) -> Bool {
    sortable0.isPriority == sortable1.isPriority
    ? sortable0.ordering < sortable1.ordering
    : sortable0.isPriority
  }
}

这将允许实现以下内容:

sortableArray.sorted()

1
我在Swift 3中创建了一篇关于如何做到简单易读的博客文章。您可以在这里找到它:

http://master-method.com/index.php/2016/11/23/sort-a-sequence-i-e-arrays-of-objects-by-multiple-properties-in-swift-3/

您还可以在GitHub存储库中找到代码:

https://github.com/jallauca/SortByMultipleFieldsSwift.playground

如果你有一个位置列表,你就可以做到这一点:
struct Location {
    var city: String
    var county: String
    var state: String
}

var locations: [Location] {
    return [
        Location(city: "Dania Beach", county: "Broward", state: "Florida"),
        Location(city: "Fort Lauderdale", county: "Broward", state: "Florida"),
        Location(city: "Hallandale Beach", county: "Broward", state: "Florida"),
        Location(city: "Delray Beach", county: "Palm Beach", state: "Florida"),
        Location(city: "West Palm Beach", county: "Palm Beach", state: "Florida"),
        Location(city: "Savannah", county: "Chatham", state: "Georgia"),
        Location(city: "Richmond Hill", county: "Bryan", state: "Georgia"),
        Location(city: "St. Marys", county: "Camden", state: "Georgia"),
        Location(city: "Kingsland", county: "Camden", state: "Georgia"),
    ]
}

let sortedLocations =
    locations
        .sorted(by:
            ComparisonResult.flip <<< Location.stateCompare,
            Location.countyCompare,
            Location.cityCompare
        )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接