日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Swift之深入解析如何进行多重条件排序

發(fā)布時(shí)間:2024/5/21 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Swift之深入解析如何进行多重条件排序 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、前言

  • 在一個(gè)條件或者單個(gè)屬性上進(jìn)行排序非常簡(jiǎn)單, Swift 本身就有相關(guān)的功能。
  • 如下所示,對(duì) int 數(shù)組進(jìn)行排序的例子:
let numbers = [3, 5, 6, 1, 8, 2] let sortedNumbers = numbers.sorted { (lhs, rhs) inreturn lhs < rhs }// [1, 2, 3, 5, 6, 8]
  • 但有時(shí)需要根據(jù)多個(gè)條件或?qū)傩詠磉M(jìn)行排序,那么該怎么處理呢?為了演示這一點(diǎn),我們可以創(chuàng)建一個(gè)結(jié)構(gòu)體來說明。如下所示,現(xiàn)有一個(gè)簡(jiǎn)單的 BlogPost 結(jié)構(gòu)體,它包含帖子標(biāo)題和兩個(gè)統(tǒng)計(jì)數(shù)據(jù),即瀏覽次數(shù) pageView 和會(huì)話持續(xù)時(shí)間 sessionDuration:
struct BlogPost {let title: Stringlet pageView: Intlet sessionDuration: Double }
  • Sample 數(shù)據(jù):
extension BlogPost {static var examples: [BlogPost] = [BlogPost(title: "Alice", pageView: 1, sessionDuration: 3),BlogPost(title: "Peter", pageView: 1, sessionDuration: 2),BlogPost(title: "Kofi", pageView: 1, sessionDuration: 1),BlogPost(title: "Akosua", pageView: 5, sessionDuration: 2),BlogPost(title: "Abena", pageView: 4, sessionDuration: 10)] }
  • 如果想查看哪些文章表現(xiàn)良好,可以按照瀏覽次數(shù)對(duì)它們直接進(jìn)行排序,但是很多帖子都不那么流行,頁(yè)面瀏覽量也一樣。在這種情況下,需要根據(jù)另一個(gè)條件或?qū)傩詠磉M(jìn)行進(jìn)一步的排序。下面來分析一下多屬性排序,它們有各種各樣的方法來解決這個(gè)問題,這里只展示沒有任何復(fù)雜概念的最基本的方法,一旦了解了基本原理,就可以隨心所欲地進(jìn)階。

二、多條件排序

  • 多條件排序是指比較第一個(gè)條件的排序,只有當(dāng)?shù)谝粋€(gè)條件相等時(shí),才轉(zhuǎn)到下一個(gè)條件,直到找到一個(gè)不相等的條件。
  • 偽代碼如下所示:
let sortedObjects = objects.sorted { (lhs, rhs) infor (lhsCriteria, rhsCriteria) in [(lhsCrtria1, rhsCriteria1), (lhsCrtria2, rhsCriteria2), (lhsCrtria3, rhsCriteria3), ... , (lhsCrtriaN, rhsCriteriaN)] { // ① if lhsCriteria == rhsCriteria { // ②continue}return lhsCriteria < rhsCriteria // ③} }
    • ① 從最重要的一個(gè)(也就是第一個(gè))開始,循環(huán)遍歷條件列表;
    • ② 如果這個(gè)順序條件相等,不能根據(jù)它來決定順序,就跳到下一個(gè)條件;
    • ③ 如果可以根據(jù)條件決定兩個(gè)對(duì)象之間的順序,就停止并返回結(jié)果。

三、按照兩個(gè)字段對(duì) object 數(shù)組進(jìn)行排序

  • 使用前面提到的場(chǎng)景,我們希望根據(jù)表現(xiàn)對(duì) BlogPost 進(jìn)行排序,表現(xiàn)取決于頁(yè)面瀏覽次數(shù) pageView,如果瀏覽次數(shù)相同,再看 sessionDuration。
  • 如下所示,是上一個(gè)例子中用到的 BlogPost 結(jié)構(gòu)體和對(duì)應(yīng)的 sample 數(shù)據(jù):
struct BlogPost {let title: Stringlet pageView: Intlet sessionDuration: Double }extension BlogPost {static var examples: [BlogPost] = [BlogPost(title: "Alice", pageView: 1, sessionDuration: 3),BlogPost(title: "Peter", pageView: 1, sessionDuration: 2),BlogPost(title: "Kofi", pageView: 1, sessionDuration: 1),BlogPost(title: "Akosua", pageView: 5, sessionDuration: 2),BlogPost(title: "Abena", pageView: 4, sessionDuration: 10)] }
  • 衡量表現(xiàn)的方法可以翻譯成下面這樣的代碼:
let popularPosts = BlogPost.examples.sorted { (lhs, rhs) in if lhs.pageView == rhs.pageView { // ① return lhs.sessionDuration > rhs.sessionDuration }return lhs.pageView > rhs.pageView // ② }
    • ① 如果博客文章有相同的訪問次數(shù),使用訪問時(shí)間;
    • ② 如果訪問次數(shù)不相等,可以直接根據(jù)訪問次數(shù)來排序(使用降序)。
  • 排序的結(jié)果:
[BlogPost(title: "Akosua", pageView: 5, sessionDuration: 2.0), BlogPost(title: "Abena", pageView: 4, sessionDuration: 10.0), BlogPost(title: "Alice", pageView: 1, sessionDuration: 3.0), BlogPost(title: "Peter", pageView: 1, sessionDuration: 2.0), BlogPost(title: "Kofi", pageView: 1, sessionDuration: 1.0)]

四、按照多個(gè)字段對(duì) object 數(shù)組進(jìn)行排序

  • 不難發(fā)現(xiàn),根據(jù)兩個(gè)條件來排序非常簡(jiǎn)單,讓我們引入更多的條件,如果博客文章的表現(xiàn)相同,按照 title 排序,添加更多的 sample 數(shù)據(jù):
extension BlogPost {static var examples2: [BlogPost] = [BlogPost(title: "Zoo", pageView: 5, sessionDuration: 2),BlogPost(title: "Alice", pageView: 1, sessionDuration: 3),BlogPost(title: "Peter", pageView: 1, sessionDuration: 2),BlogPost(title: "Kofi", pageView: 1, sessionDuration: 1),BlogPost(title: "Akosua", pageView: 5, sessionDuration: 2),BlogPost(title: "Abena", pageView: 4, sessionDuration: 10),BlogPost(title: "Angero", pageView: 1, sessionDuration: 2)] }
  • 兩個(gè)條件和三個(gè)條件沒什么區(qū)別,可以沿用相同的邏輯:
let popularPosts = BlogPost.examples2.sorted { (lhs, rhs) inif lhs.pageView == rhs.pageView {// 添加另一個(gè)if來檢查博客文章是否具有相同的會(huì)話持續(xù)時(shí)間,如果它們具有相同的頁(yè)面瀏覽次數(shù)和會(huì)話持續(xù)時(shí)間,則按標(biāo)題對(duì)它們進(jìn)行排序if lhs.sessionDuration == rhs.sessionDuration { return lhs.title < rhs.title} return lhs.sessionDuration > rhs.sessionDuration}return lhs.pageView > rhs.pageView }
  • 排序結(jié)果:
[BlogPost(title: "Akosua", pageView: 5, sessionDuration: 2.0),BlogPost(title: "Zoo", pageView: 5, sessionDuration: 2.0),BlogPost(title: "Abena", pageView: 4, sessionDuration: 10.0),BlogPost(title: "Alice", pageView: 1, sessionDuration: 3.0),BlogPost(title: "Angero", pageView: 1, sessionDuration: 2.0),BlogPost(title: "Peter", pageView: 1, sessionDuration: 2.0),BlogPost(title: "Kofi", pageView: 1, sessionDuration: 1.0)]
  • 可以對(duì)兩個(gè)和三個(gè)條件使用相同的邏輯,這里唯一的問題是,條件越多,需要的嵌套就越多。如下所示,這是一個(gè)多條件的例子,可能會(huì)導(dǎo)致 pyramid of doom:
let popularPosts = BlogPost.examples2.sorted { (lhs, rhs) inif lhs.pageView == rhs.pageView {if lhs.sessionDuration == rhs.sessionDuration { if lhs.nextCriteria == rhs.nextCriteria { if lhs.nextCriteria == rhs.nextCriteria { ....}...}...} return lhs.sessionDuration > rhs.sessionDuration}return lhs.pageView > rhs.pageView }

五、按照 N 個(gè)字段對(duì) object 數(shù)組進(jìn)行排序

  • 為了避免 pyramid of doom,再看看之前的偽代碼:
let sortedObjects = objects.sorted { (lhs, rhs) infor (lhsCriteria, rhsCriteria) in [(lhsCrtria1, rhsCriteria1), (lhsCrtria2, rhsCriteria2), (lhsCrtria3, rhsCriteria3), ... , (lhsCrtriaN, rhsCriteriaN)] {if lhsCriteria == rhsCriteria {continue}return lhsCriteria < rhsCriteria} }
  • 上面的代碼不是解決類似問題的唯一方式,不過關(guān)鍵思路是相似的,關(guān)鍵思路就是把多個(gè)條件打包到一個(gè)集合當(dāng)中去遍歷:
extension BlogPost {static var examples2: [BlogPost] = [BlogPost(title: "Zoo", pageView: 5, sessionDuration: 2),BlogPost(title: "Alice", pageView: 1, sessionDuration: 3),BlogPost(title: "Peter", pageView: 1, sessionDuration: 2),BlogPost(title: "Kofi", pageView: 1, sessionDuration: 1),BlogPost(title: "Akosua", pageView: 5, sessionDuration: 2),BlogPost(title: "Abena", pageView: 4, sessionDuration: 10),BlogPost(title: "Angero", pageView: 1, sessionDuration: 2)] }typealias AreInIncreasingOrder = (BlogPost, BlogPost) -> Bool // ①let popularPosts = BlogPost.examples2.sorted { (lhs, rhs) in let predicates: [AreInIncreasingOrder] = [ // ②{ $0.pageView > $1.pageView },{ $0.sessionDuration > $1.sessionDuration},{ $0.title < $1.title }]for predicate in predicates { // ③if !predicate(lhs, rhs) && !predicate(rhs, lhs) { // ④continue // ⑤}return predicate(lhs, rhs) // ⑥}return false }
  • 分析說明:
    • ① 聲明一個(gè)別名 AreInIncreasingOrder 用來匹配排序閉包,這可以提高對(duì)謂詞集合聲明的可讀性;
    • ② 聲明一個(gè)謂詞集合;
    • ③ 遍歷這個(gè)謂詞集合;
    • ④ 這里是關(guān)鍵邏輯,想要檢查條件是否能決定博文順序,但是 AreInIncreasingOrder 返回了一個(gè)布爾值,我們應(yīng)該如何判斷它們是否相等? 先來看看定義,AreInIncreasingOrder 是一個(gè)謂詞,它會(huì)在第一個(gè)參數(shù)能決定順序時(shí)返回 true 否則返回 false,兩個(gè)變量只有在各自都不是升序時(shí)才相等;這意味著無論參數(shù)順序如何,謂詞都必須是 false,換言之 lhs.pageView < rhs.pageView 和 rhs.pageView < lhs.pageView 必須等于 false 才能決定順序相等,這就是 !predicate(lhs, rhs) && !predicate(rhs, lhs) 這句代碼的意思;
    • ⑤ 如果順序相等,那么 continue 到下一個(gè)謂詞;
    • ⑥ 如果順序不相等,那么可以用這個(gè)謂詞來排序。
  • 排序結(jié)果:
[BlogPost(title: "Akosua", pageView: 5, sessionDuration: 2.0), BlogPost(title: "Zoo", pageView: 5, sessionDuration: 2.0), BlogPost(title: "Abena", pageView: 4, sessionDuration: 10.0), BlogPost(title: "Alice", pageView: 1, sessionDuration: 3.0), BlogPost(title: "Angero", pageView: 1, sessionDuration: 2.0), BlogPost(title: "Peter", pageView: 1, sessionDuration: 2.0),BlogPost(title: "Kofi", pageView: 1, sessionDuration: 1.0)]

總結(jié)

以上是生活随笔為你收集整理的Swift之深入解析如何进行多重条件排序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。