ts实现忽略大小写的字符串排序的两种方法
程序员文章站
2023-11-02 15:39:46
这里有一个奇奇怪怪的学生数组:
const students = [
{ name: 'aaa', age: 18, sex: "man&...
这里有一个奇奇怪怪的学生数组:
const students = [ { name: 'aaa', age: 18, sex: "man" }, { name: 'aaab', age: 21, sex: "man" }, { name: 'aaabc', age: 23, sex: "woman" }, { name: 'aaaab', age: 16, sex: "man" }, { name: 'aaaac', age: 27, sex: "man" }, { name: 'abcd', age: 15, sex: "man" } ];
现在呢我们要按照这奇奇怪怪的姓名来排序。
规则:忽略大小写,根据字符在hash table里位置进行排序。
先写出排序的方法。
依旧是参照阮一峰的快速排序法 。
传入三个参数arr、selector、compare,分别代表需要排序的数组、排序依据、以及可选的比较方法。
function orderbyname(arr: titem[], selector: (i: titem) => tvalue, compare?: (a: tvalue, b: tvalue) => number): titem[] { if (arr.length <= 1) { return arr; } if (!compare) { compare = (a, b) => a < b ? -1 : a > b ? 1 : 0; } //如果没有传入compare方法,就按照以上的方法来排序。 const orderbyarray = arr.slice(0); const pivotindex = math.floor(orderbyarray.length / 2); const pivotitem = orderbyarray.splice(pivotindex, 1)[0]; const pivotvalue = selector(pivotitem); const left = [] as titem[]; const right = [] as titem[]; for (const i of orderbyarray) { if (compare(selector(i), pivotvalue) < 0) { left.push(i); } else { right.push(i); } } return orderbyname(left, selector, compare).concat([pivotitem], orderbyname(right, selector, compare)); } //调用方法: const nameorder = orderbyname(students, i => i.name, ignorecasestringcompare); console.log(nameorder);
接下来,有两种不同的比较字符串的方法。
方法一是我自己想的(说明自己还是有点进步的嘻嘻)。
方法二是师父补充的,可以提高函数运行的效率。
方法一
//ignorecasecharcompare方法用来比较两个字母在hash table里的位置大小 function ignorecasecharcompare(a: string, b: string): number { //传入两个string类型的参数,得出number类型的结果。 return a.touppercase().charcodeat(0) - b.touppercase().charcodeat(0); //忽略大小写,所以全部转换为touppercase() } //ignorecasestringcompare方法用来比较两个字符串 function ignorecasestringcompare(a: string, b: string): number { const alen = a.length; const blen = b.length; const len = alen - blen < 0 ? alen : blen; // const len = math.min(alen,blen); 内置math方法也可以 for (let i = 0; i < len; i++) { const result = ignorecasecharcompare(a.charat(i), b.charat(i)); if (result !== 0) { return result; } // 一直遍历,直到某位不相等,或者一个字符串已经遍历完为止,输出比较结果,跳出函数。 } if (alen < blen) { return -1; // 如果不满足上一个判断条件的话,再对比两个字符串长度。 } else { return 1; } }
方法一的缺点在于 需要一次又一次地遍历字符串的每一个字母,效率比较低。
方法二
function ignorecasecharcompare(a: string, b: string): number { return a.touppercase().charcodeat(0) - b.touppercase().charcodeat(0); } // 同样是比较字符的方法。 function ignorecasestringcompare(a: string, b: string): number { function ignorecasestringcomparerec(a: string, b: string, index: number): number { // 这个函数的关键,是传入一个index,这个index通常从0开始,代表着字符串(从左到右)的第一位 if (index + 1 > a.length) { if (a.length === b.length) { return 0; } return -1; } // 以上这个判断的意思就是,执行到这里如果字符串长度已经小于index了,说明两个字符串的前几位都是相同的,位数短的那一个排在前面,相等的代表相同。 if (index + 1 > b.length) { return 1; } const result = ignorecasecharcompare(a.charat(index), b.charat(index)); if (result !== 0) { return result; } return ignorecasestringcomparerec(a, b, index + 1);执行到这里没有判断出结果的,index+1回到函数顶部重新执行,也就是比较下一个字符 } return ignorecasestringcomparerec(a, b, 0); }
第二种方法就是一个一个字符去比较,而不是全部遍历他的length,比较到某一位字符如果有结果的话就直接return,无需再进行下面的比较了。
其实第二种方法中用到的length可以用别的办法来代替,但是应该比较复杂,所以师父就没有告诉我。有时间的话再演技一下具体如何实现吧!