算法入门:数组函数的实现

133 阅读1分钟

数组函数的实现

1. 内置方法 - 排序函数sort():

  • 参数:函数(规定排序的顺序),可选
  • 返回值:对数组的引用【改变原数组
  • 使用方式:
var points = [40,100,1,5,25,10];  
points.sort();// 结果是[1, 10, 100, 25, 40, 5]
points.sort(function(a,b){return a-b});

⚠⚠️:默认排序顺序为按字母升序。当数字是按字母顺序排列时"40"将排在"5"前面。使用数字排序,你必须通过一个函数作为参数来调用。

  • 手写算法:快排

/**
 * @param {Array} arr
 * @param {Function} fn
 * @return {Array}
 */
var sortBy = function(arr, fn) {
     let len = arr.length;
    //  递归结束条件
     if(len<=1) return arr;
     let mid = Math.floor(len/2);
     let left=[];
     let right =[];

     for(let i=0; i<len;i++){
         // 中间值不要放进切分的数组中
         if(fn(arr[i]) === fn(arr[mid])) continue;
         
         if(fn(arr[i])<fn(arr[mid])){
             left.push(arr[i])
         }else{
             right.push(arr[i])
         }
        
     }
    return [...sortBy(left,fn),arr[mid],...sortBy(right,fn)];
};

2. 内置方法 - 过滤函数 filter():

  • 不检测空数组
  • 参数:
    • 函数:必须
      • 函数参数:
        • 当前值,索引,当前数组
    • thisValue:可选,省略的话this是undefined
  • 返回值:新数组,[不改变] 原数组
var filter = function(arr, fn) {
    let filteredArr =[];
    for(let i=0; i< arr.length;i++){
        if(fn(arr[i], i)){
            filteredArr.push(arr[i])
        }
    }
    return filteredArr;
};

3. 内置方法 - 映射函数map

/**
 * @param {number[]} arr
 * @param {Function} fn
 * @return {number[]}
 */
var map = function(arr, fn) {
    let returnedArray = [];
    for(let i =0; i<arr.length; i++){
        const newItem = fn(arr[i],i)
        returnedArray.push(newItem);
    }
    return returnedArray;
};

4. 内置方法 - 归约函数reduce

  • 还有个reduceRight
/**
 * @param {number[]} nums
 * @param {Function} fn
 * @param {number} init
 * @return {number}
 */
var reduce = function(nums, fn, init) {
 let val = init;
 if(nums.length ===0 ){
     return val;
 }  

 for(var i=0; i<nums.length; i++){
     val = fn(val,nums[i]);
 }
 return val;
};

5. 复合函数

请你编写一个函数,它接收一个函数数组 [f1, f2, f3,…, fn] ,并返回一个新的函数 fn ,它是函数数组的 复合函数 。
[f(x), g(x), h(x)] 的 复合函数 为 fn(x) = f(g(h(x))) 。
恒等函数 f(x) = x

var compose = function(functions) {
	return function(x) {
        for(let i =functions.length-1; i>=0 ; i--){
            x = functions[i](x);
        }
        return x;
    }
};

6. 分块数组lodash 的函数 _.chunk

/**
 * @param {Array} arr
 * @param {number} size
 * @return {Array[]}
 */
var chunk = function(arr, size) {
    let index =0 ; 
    let resultArr=[];
    let row = [];
    while(index< arr.length){
        row.push(arr[index]);
        if(row.length === size){
            resultArr.push([...row])
            row = [];
        }
        index++;
    }
    row.length && resultArr.push([...row])
    return resultArr;

};

原型

1. last 函数

注意:原型上的this指向调用的对象,所以这里this是arr

Array.prototype.last = function() {
    return this.length ? this[this.length-1] : -1
};

/**
 * const arr = [1, 2, 3];
 * arr.last(); // 3
 */

2. 包装函数

构造函数中的this是指向实例。构造函数命名首字母大写

// 构造函数,需要new 声明
var ArrayWrapper = function(nums) {
     this.nums = nums;
};
// 隐形转换
ArrayWrapper.prototype.valueOf = function() {
    return this.nums.reduce((pre,cur)=>pre+cur, 0);
}

ArrayWrapper.prototype.toString = function() {
    return `[${this.nums.join()}]`
}

/**
 * const obj1 = new ArrayWrapper([1,2]);
 * const obj2 = new ArrayWrapper([3,4]);
 // console.log(obj1.nums): [1,2]
 * obj1 + obj2; // 10
 * String(obj1); // "[1,2]"
 * String(obj2); // "[3,4]"
 */