工做到了這個年數, 感受那些基本函數語法已經跟人合一了, 根本不會爲操做一些數據結構而思考半天了. 在作小程序的時候遇到了個orderby的場景, 結果發現沒有覺得的那麼簡單. 也許是以前不求甚解的緣由, 那麼如今來解決orderby的問題.數據庫
在小程序中有個將list的某一條置頂的需求, 在初始化數據到時候可使用數據庫的orderby, 但在更新數據之後再從新初始化就顯得有些不妥, 因此我嘗試直接使用computed列表來解決這個問題.小程序
因此如今的問題是: 輸入list, 輸出orderby置頂字段.數組
以前覺得的sort很簡單, 我就嘗試了: arr.sort(i => i.stick)
. 字面看起來是根據stick字段來排序. 輸出結果一團糟. 仔細思考了下又嘗試了別的方法, 仍是失敗, 才決定仔細想一下應該如何處理.數據結構
先說一下以前對sort的理解.dom
sort接受的參數返回大於0或者小於0. 根據結果來排序.函數
因此有一個快速shuffle數組的方法:code
arr.sort(() => Math.random() - 0.5)
由於函數的返回結果一半是大於0一半是小於0的(不嚴格, 但以後也認爲機率是一半一半). 因此任何輸出進行了如此處理, 都會變成一個隨機順序的數組.排序
另一個例子, 對一個數組: [1, 2, 3, 4, 5, 10, 11, 12]
進行排序, 若是不傳參數排序結果是錯的, 由於默認是localCompare. 因此要寫成:get
arr.sort((a, b) => a - b)
這樣才能獲得正確從小到大的排列.string
以上就是我多年以來對sort的全部理解. 因此纔會寫出上面的: arr.sort(i => i.stick)
這樣搞笑的東西. 由於理解是有問題的.
由於不知道sort函數獲得告終果後是如何排序的. 因此對sort的理解有問題. 而咱們知道reduce就是從頭至尾遍歷並傳遞每次計算的結果. sort殊不知道. 因此打出每次的返回值來看一下每次獲得返回值後sort作了些什麼.
咱們要對不一樣數組進行一樣的操做, 排序方法是同樣的, 先寫一下:
const log = (a, b) => { console.log(a, b, a - b > 0) return a - b }
開始對不一樣數組進行排序: 先來1到5
[1, 2, 3, 4, 5].sort(log)
結果: [1, 2, 3, 4, 5]
2 1 true 3 2 true 4 3 true 5 4 true
嘗試: 從5到1
[5, 4, 3, 2, 1].sort(log)
結果: [1, 2, 3, 4, 5]
4 5 false 3 4 false 2 3 false 1 2 false
目前看來, sort應該是插入排序.
[3, 5, 7, 9, 2, 1, 6].sort(log)
看log的時候我把當前排序結果也打一下:
5 3 true [3, 5] 7 5 true [3, 5, 7] 9 7 true [3, 5, 7, 9] 2 9 false // 2仍是與當前最大的9比.結果第一次false 2 7 false // 因而一路比下來 2 5 false 2 3 false // 比到最小的, 因而肯定了位置 [2, 3, 5, 7, 9] 1 5 false // 1選擇了與5比, 此時5是中間位置的數, 而不是最大的數 1 3 false // 而後一個一個比較下來 1 2 false [1, 2, 3, 5, 7, 9] 6 5 true // 6仍是於5比, 此時5也是中間位置的數 6 9 false // 沒有選擇與7, 而是與9比了 6 7 false
從這些log能得出一些粗淺的結論:
首先明確思路:
sort認爲每一個元素之間的關係是比大小, 因此咱們須要作的是寫出任意兩個元素的相對順序的廣泛公式.
先構建一組數據:
let gnrt = () => ({ age: Math.round(Math.random() * 50), height: Math.round(Math.random() * 200) }) let arr = Array.from({length: 10}).map(() => gnrt())
咱們先創建純數字, 無順序
的orderby來理這個思路.
let orderby = function (arr, ...orders) { return arr.sort((a, b) => { let res = 0 for (let order of orders) { if (a[order] - b[order] !== 0) { res = a[order] - b[order] break } } return res }) }
調用orderby(arr, 'height', 'age')
就獲得了理想的orderby結果了: 根據權重排序, 若是都同樣就保持順序.
#後續#
這個思路清晰之後, 作兼容就容易了:
固然, 功能越完善的函數就越複雜, 函數自己只是函數複雜度和業務複雜度交換的做用. 具體實現就不寫了.
咱們已經想清楚了orderby的實現, 那麼置頂排序是stick這個布爾值字段, 就必須根據我上面說的傳函數進去, 而且改寫orderby函數.
這樣又要多些2個函數, 因此我選擇:
[...arr.filter({stick} => stick), ...arr.filter({stick} => !stick)]
搞定.