數組排序,字符串math,replace練習

1. 關於數組排序數組

    排序一直是程序設計中的熱門話題。在js中,數組有個sort()方法。在不傳參數默認狀況下,數組的sort()方法原理是:對數每項調用toString()方法,比較字符串按升序排序數組。看下面的例子。函數

var arrA = [null, undefined, 3, 2, 5, 21, {toString:function() {
    return 1;
}, p:'hello'}];
var arrB = [undefined, null, 3, 2, 5, 21,{toString:function() {
    return 1;
}, p: 'hello'}];    
var arrC = [null, undefined, 3, 2, 21, {toString:function() {
    return 1;
}, p:'hello'},
{a:1},
{toString:function(){return 'p'}},
{toString:function(){return 'oa'}},
{toString:function(){return 'p'}},
{toString:function(){return 'v'}}, 'u', 'v', 'nukk','nulk'
];

arrA.sort();//結果是:[Object, 2, 21, 3, 5, null, undefined]
arrB.sort();//結果是:[Object, 2, 21, 3, 5, null, undefined]
arrA.sort()[0].p;//hello
arrC.sort();

上面的例子說明:測試

a. sort()方法不傳比較函數時,的確是對每項調用了toString()方法[對null應該是使用String(null)]轉換成字符串再進行升序排序的this

b. undefined不會參與排序,直接放最後面spa

當要使用其它標準對數組進行排序時,就要傳入一個比較函數做爲參數。原理及執行過程沒有弄清楚(有知道的請告訴下),但獲得以下結論:prototype

var arrD = [3, 5, 1, 8, 10];

console.log(arrD.sort(compare));

function compare(v1, v2) {
    var a = v1;
    var b = v2;
    console.log('v1='+v1 + '||'+ 'v2='+v2);
    //return v1 - v2; //升序
    //return v2 - v1;//降序
    //return -1;  //原樣輸出
    //return 0; //原樣輸出
    //return 1; //反順輸出
}

下面是一個實際Demo:設計

/**
 * 爲數組實現一個排序方法,可以num、string、date、character和object的排序,
 * 對object類型排序時,按照某個屬性排序。只考慮數組中存放都是相同類型的數據
 * @param {Boolean} order 爲true表示升序,false表示降序
 * @param {String} key 對象的鍵值
 */
Array.prototype.sameTypeSort = function(order, key) {
    var type = type(this[0]);
    var ret = [], i = 0, temp, tempArr = [];
    order = order ? true : false;
    switch(type) {
        case 'string':
            ret = this.sort();//升序
            break;
        case 'number':
            ret = this.sort(ascending);
            break;
        case 'date':
            while(temp = this[i]) {
                tempArr.push(temp.getTime());
                i++;
            }
            tempArr.sort(ascending);
            break;
        default :
            while(i < this.length) {
                tempArr.push(this[i][key]);
                i++;
            }
            tempArr = tempArr.sameTypeSort(true);
    }


    //若是是時間,對象還要將還原成排序前的值
    if(type === 'date') {
        i = 0;
        while(temp = tempArr[i]) {
            ret.push(new Date(temp));
            i++;
        }
    }

    if(type === 'object') {
        i = 0;
        while(temp = tempArr[i]) {
            for(var start = 0, curObj, value; curObj = this[start]; start++) {
                value = curObj[key];
                if(value === temp) {
                    ret.push(curObj);
                    break;
                }
            }
            i++;
        }
    }

    return order ? ret : ret.reverse();

    function type(target) {
        return ({}).toString.call(target).slice(8, -1).toLocaleLowerCase();
    }
    function ascending(v1, v2) {
        return v1 - v2;
    }
};

下面是經過的Qunit的測試代碼:code

test( "數值排序", function() {
    var arr = [1,11,2,22,3,33,-5,-55, 0];
    var upOrder = [-55, -5, 0, 1,2,3,11,22, 33];

    propEqual(arr.sameTypeSort(true), upOrder, 'pass');
    propEqual(arr.sameTypeSort(false), upOrder.reverse(), 'pass');
});

test( "字符串排序", function() {
    var arr = ['aa', 'ac', 'ab', 'bc', 'ba', 'acd'];
    var upOrder = ['aa', 'ab', 'ac', 'acd', 'ba', 'bc'];

    propEqual(arr.sameTypeSort(true), upOrder, 'pass');
    propEqual(arr.sameTypeSort(false), upOrder.reverse(), 'pass');
});

test( "時間排序", function() {
    var arr = [new Date('2014/06/16 0:0:0'), new Date('2014/06/12 0:0:0'), new Date('2014/06/14 0:0:0')];

    strictEqual(arr.sameTypeSort(true)[0].getTime(), arr[1].getTime());
    strictEqual(arr.sameTypeSort(false)[0].getTime(), arr[0].getTime());
});

test( "對象排序", function() {
    var arr = [
        {key:5, f: 'x'},
        {key:2, f:'y'},
        {key:6, f:'z'}
    ];

    strictEqual(arr.sameTypeSort(true, 'key')[0].f, 'y');
    strictEqual(arr.sameTypeSort(false, 'key')[0].f,'z');
    console.log(arr.sameTypeSort(true, 'key'));
    console.log(arr.sameTypeSort(false, 'key'));
});

2. match,replace函數練習orm

a. 價格千分對象

/**
 * 在整數部分對費用進行千分。一開始想用正則來作,但實現過程當中發現各類問題,最後代碼變成下面的樣子了
 * @param {String} feeStr 有效的費用數值字符串
 * @returns {String} 進行了千分格式化後的字符串
 */
function splitFee(feeStr) {
    var ret, leftCtx, rightCtx;

    ponintPos = feeStr.indexOf('.');
    if(ponintPos !== -1) {
        leftCtx = feeStr.substring(0, ponintPos);
        rightCtx = feeStr.substring(ponintPos+1);
    } else {
        leftCtx = feeStr;
        rightCtx = '';
    }

    /*match = feeStr.match(/\./);
    leftCtx = RegExp.leftContext;//整數部分
    rightCtx = RegExp.rightContext;  使用正則會有一個Bug,若後面match匹配失敗,後面的rightCtx始終會保存前次匹配的值*/
    leftCtx = leftCtx ? leftCtx : feeStr;
    rightCtx = rightCtx ? '.'+rightCtx : '';

    ret = (leftCtx.split('').reverse().join('').replace(/(\d{3})/g, function(m, ms, offset, targetStr) {
        return m + ','
    }).split('').reverse().join('')+rightCtx).replace(/^\,/,'');

    return ret;
}

經過的Qunit測試代碼

test( "replace, match練習:數值字符串千分", function() {
    //對整數部分進行千分
    var fee1 = '1747136.51';
    var fee2 = '277136.52';
    var fee3 = '37136.53';
    var fee4 = '47136';
    var fee5 = '136';

    strictEqual(splitFee(fee1), '1,747,136.51');
    strictEqual(splitFee(fee2), '277,136.52');
    strictEqual(splitFee(fee3), '37,136.53');
    strictEqual(splitFee(fee4), '47,136');
    strictEqual(splitFee(fee5), '136');
});

b. 交換包含兩個單詞的字符串

/**
 * 交換單詞字符串中的兩個單詞
 * @param str
 * @returns {String}
 */
function swapTwoWords(str) {
    return str.replace(/(\w+)\s(\w+)/, '$2 $1');
    //return str.split(' ').reverse().join(' '); 使用數組
}

//Qunit測試
test( "replace練習:交換單詞", function() {
    var str = 'hello world';

    strictEqual(swapTwoWords(str), 'world hello');
});

c. 字符串模板替換方法

/**
 * 字符串模板替換方法
 * @param {String} str
 * @param {Object} obj
 */
function format(str, obj) {
    return str.replace(/({\w+})/gm, function(m, ms, offset, targetStr) {
        return obj[m.substring(1, m.length - 1)];
    });
}

//Qunit測試
test( "字符串模板format方法", function() {
    var str = '<div>{id}</div></div>{name}</div>';

    strictEqual(format(str, {id:100, name:'xyz', address:'cd'}), '<div>100</div></div>xyz</div>');
});
相關文章
相關標籤/搜索