如何在Google Spreadsheet脚本中按自定义字母表实现排序?
如何在Google Sheets脚本中实现自定义字母表排序?
要实现基于自定义字母表的排序,核心是建立字符到排序权重的映射,然后编写自定义字符串比较函数替代默认的localeCompare。以下是修改后的完整代码:
const VOWEL_PATTERN = /[ieaou]/i; const ALPHABETICAL_ORDER = 'ieaoumnqgdbptkhsfvzjxcCwylr'; // 预创建字符-权重映射,O(1)查询效率 const CHAR_WEIGHT = new Map([...ALPHABETICAL_ORDER].map((char, index) => [char, index])); function onOpen() { const ui = SpreadsheetApp.getUi(); ui.createMenu("Sort") .addItem("按长度再按自定义字母排序", "sortByLength") .addItem("按音节数再按自定义字母排序", "sortBySyllable") .addToUi(); } // 自定义字符串比较函数:按自定义字母表顺序排序 function customCompare(strA, strB) { const maxLength = Math.max(strA.length, strB.length); for (let i = 0; i < maxLength; i++) { const charA = strA[i] || ''; const charB = strB[i] || ''; // 不在自定义表中的字符权重设为无穷大,排在所有自定义字符之后 const weightA = CHAR_WEIGHT.get(charA) ?? Infinity; const weightB = CHAR_WEIGHT.get(charB) ?? Infinity; if (weightA !== weightB) { return weightA - weightB; } } // 前面字符完全相同,短字符串排前面 return strA.length - strB.length; } function sortBySyllable() { const range = SpreadsheetApp.getActive().getDataRange(); const array = range.getValues(); const sortedArray = [array[0]].concat( array.slice(1).sort((a, b) => { const xp = a[0]; const yp = b[0]; return ( xp.split(VOWEL_PATTERN).length - yp.split(VOWEL_PATTERN).length || xp.length - yp.length || customCompare(xp, yp) // 替换为自定义比较 ); }) ); range.setValues(sortedArray); } function sortByLength() { const range = SpreadsheetApp.getActive().getDataRange(); const array = range.getValues(); const sortedArray = [array[0]].concat( array.slice(1).sort((a, b) => { const xp = a[0]; const yp = b[0]; return xp.length - yp.length || customCompare(xp, yp); // 替换为自定义比较 }) ); range.setValues(sortedArray); }
关键细节说明
- 高效权重映射:用
Map存储每个字符对应的排序权重,查询时复杂度为O(1),比每次调用indexOf(O(n))更高效,尤其处理大量数据时优势明显。 - 自定义比较逻辑:
- 逐个字符对比权重,权重小的字符对应的字符串排前面
- 若其中一个字符串先结束,短字符串排在前面
- 不在自定义字母表中的字符,权重设为
Infinity,会排在所有自定义字符之后
- 兼容原有逻辑:仅替换排序链中的字母顺序比较部分,保留原有的“长度优先”“音节数优先”的排序规则。
内容的提问来源于stack exchange,提问作者Lance Pollard
相关产品推荐
相关产品推荐

