深入解析:處理中文數字的自訂排序函數

在程式開發中,經常需要處理各種複雜的排序需求。今天,遇到一個需求需要對某個項目的欄位排序,欄位裡面開頭儲存著(一)、(二)等等的中文數字,所以寫下了這個自訂排序函數來處理,這個函數能夠處理帶有中文數字前綴的字串,並按照這些數字的順序進行排序。

函數概述

這個自訂排序函數主要用於排序一個物件陣列 scope.datalist。每個物件都有一個 Catacory 屬性,值可能包含像 "(一)"、"(二)"、"(十)"、"(二十)" 這樣的中文數字前綴,可以處理到(九十九)。函數的目標是根據這些前綴的數值大小對陣列進行排序,如果沒有排序的數字,設定為100,達成無順序的項目放到最後面的效果。

程式碼解析

讓我們逐步分解這個函數的實現:

1
2
3
4
5
6
7
8
9
10
function customSort(a, b) {
// ... (getNumber函數的實現)
const aNum = getNumber(a.Catacory);
const bNum = getNumber(b.Catacory);
if (aNum !== bNum) {
return aNum - bNum;
}
// 如果數字相同,按原始順序排序
return scope.datalist.indexOf(a) - scope.datalist.indexOf(b);
}

1. getNumber 函數

這是整個排序邏輯的核心,它負責將中文數字轉換為阿拉伯數字:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const getNumber = (str) => {
const match = str.match(/^\(([一二三四五六七八九十]+)\)/);
if (match) {
const numStr = match[1];
const numMap = { 一: 1, 二: 2, 三: 3, 四: 4, 五: 5, 六: 6, 七: 7, 八: 8, 九: 9, 十: 10 };
if (numStr.length === 1) {
return numMap[numStr] || 0;
} else if (numStr.startsWith('十')) {
return numStr.length === 2 ? 10 + numMap[numStr[1]] : 10;
} else {
return numMap[numStr[0]] * 10 + (numMap[numStr[2]] || 0);
}
}
return 100;
};

正則表達式匹配

  • 使用正則表達式 /^\(([一二三四五六七八九十]+)\)/ 來匹配括號內的中文數字。
  • ^ 確保匹配從字串開始。
  • \(\) 匹配左右括號。
  • ([一二三四五六七八九十]+) 捕獲括號內的中文數字。

數字轉換邏輯

  • 對於單個字符(如 "一", "二"),直接返回對應的數值。
  • 對於 "十" 開頭的數字:
    • "十" 返回 10
    • "十一" 到 "十九" 返回 11 到 19
  • 對於其他兩位數:
    • 首位數字 * 10 + 末位數字

2. 比較邏輯

1
2
3
4
5
const aNum = getNumber(a.Catacory);
const bNum = getNumber(b.Catacory);
if (aNum !== bNum) {
return aNum - bNum;
}

這部分代碼比較兩個轉換後的數字。如果不相等,則按數字大小排序。

3. 處理相等情況

1
return scope.datalist.indexOf(a) - scope.datalist.indexOf(b);

當兩個項目的數字相同時,此代碼保持它們在原陣列中的相對順序。

應用排序

最後,將自訂排序函數應用到陣列:

1
scope.datalist.sort(customSort);

這行代碼使用我們定義的 customSort 函數對 scope.datalist 進行排序。

結論

這個自訂排序函數展示了如何處理複雜的排序需求,特別是在處理非標準數字格式時。它結合了正則表達式、字符串處理和數學運算,提供了一個靈活而強大的排序解決方案。

這種方法不僅適用於處理中文數字,還可以擴展到其他類似的排序需求。通過理解和掌握這種技術,我們可以在日後的開發中更好地處理各種複雜的數據排序問題。