美文网首页
「TS」练习 · 两种方法实现忽略大小写的字符串排序

「TS」练习 · 两种方法实现忽略大小写的字符串排序

作者: DebraJohn | 来源:发表于2018-07-18 23:26 被阅读0次

    这里有一个奇奇怪怪的学生数组:

    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<Titem, Tvalue>(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可以用别的办法来代替,但是应该比较复杂,所以师父就没有告诉我。有时间的话再演技一下具体如何实现吧!

    相关文章

      网友评论

          本文标题:「TS」练习 · 两种方法实现忽略大小写的字符串排序

          本文链接:https://www.haomeiwen.com/subject/xqfzpftx.html