3 回答

TA貢獻(xiàn)1891條經(jīng)驗(yàn) 獲得超3個(gè)贊
穩(wěn)定的排序
假設(shè)你有一個(gè)像這樣的數(shù)組:
['Kale', 'Kaleidoscope', 'Aardvark', 'Apple', 'Leicester', 'Lovely']
而現(xiàn)在你只想對第一個(gè)字母進(jìn)行排序:
usort($array, function($a, $b) { return strcmp($a[0], $b[0]);});
結(jié)果如下:
['Apple', 'Aardvark', 'Kale', 'Kaleidoscope', 'Lovely', 'Leicester']
那種不穩(wěn)定!
敏銳的觀察者可能已經(jīng)注意到,數(shù)組排序算法(QuickSort)沒有產(chǎn)生穩(wěn)定的結(jié)果,并且沒有保留相同第一個(gè)字母的單詞之間的原始順序。這個(gè)案例很簡單,我們應(yīng)該比較整個(gè)字符串,但是我們假設(shè)你的用例更復(fù)雜,比如不同字段上的兩個(gè)連續(xù)排序不應(yīng)該抵消彼此的工作。
施瓦茨變換
Schwartzian變換,也稱為decorate-sort-undecorate習(xí)語,使用固有的不穩(wěn)定排序算法實(shí)現(xiàn)穩(wěn)定排序。
首先,使用包含主鍵(值)和輔助鍵(其索引或位置)的另一個(gè)數(shù)組來裝飾每個(gè)數(shù)組元素:
array_walk($array, function(&$element, $index) { $element = array($element, $index); // decorate});
這會(huì)將數(shù)組轉(zhuǎn)換為:
[ ['Kale', 0], ['Kaleidoscope', 1], ['Aardvark', 2], ['Apple', 3], ['Leicester', 4], ['Lovely', 5]]
現(xiàn)在,我們調(diào)整比較步驟; 我們再次比較第一個(gè)字母,但如果它們相同,則使用二級密鑰保留原始排序:
usort($array, function($a, $b) { // $a[0] and $b[0] contain the primary sort key // $a[1] and $b[1] contain the secondary sort key $tmp = strcmp($a[0][0], $b[0][0]); if ($tmp != 0) { return $tmp; // use primary key comparison results } return $a[1] - $b[1]; // use secondary key});
之后,我們不合理:
array_walk($array, function(&$element) { $element = $element[0];});
最終結(jié)果:
['Aardvark', 'Apple', 'Kale', 'Kaleidoscope', 'Leicester', 'Lovely']
重用怎么樣?
您必須重寫比較函數(shù)才能使用轉(zhuǎn)換后的數(shù)組元素; 您可能不想編輯精細(xì)的比較函數(shù),因此這里是比較函數(shù)的包裝器:
function stablecmp($fn){ return function($a, $b) use ($fn) { if (($tmp = call_user_func($fn, $a[0], $b[0])) != 0) { return $tmp; } else { return $a[1] - $b[1]; } };}
讓我們使用這個(gè)函數(shù)編寫排序步驟:
usort($array, stablecmp(function($a, $b) { return strcmp($a[0], $b[0]);}));
瞧!您的原始比較代碼又回來了。
- 3 回答
- 0 關(guān)注
- 974 瀏覽
添加回答
舉報(bào)