zoukankan      html  css  js  c++  java
  • ES6高级使用技巧(reduce,filter篇)

    本周总结

    这几天在写Echarts自定义需求的时候发现了,图形化算法和函数式编程的应用场景,很多时候我们现在学的东西并一定在当前的这种状态有用,但是兴趣吧,喜欢就去学呗,没准在日后的工作日常中用到了

    我喜欢这种既学习到东西还能随便给我发发工资的生活

    热情只有在某个年龄段才会有的,所以把握现在,失去热情就等于失去了生活的乐趣

    以前我写过几遍关于reduce 的文章,但是可能没有连贯性或者说没有单一,就在前几天在解决Echarts自定义需求的时候,终于发现了结合的用武之地了

    随便把filter也介绍下,毕竟我也用的少

    reduce 特性

    [1,2,3,4,4].reduce((acc,val)=>
                      //第一种
                       acc.concat(xxx),[]
                       //第二种
                       (acc.push(xxx),acc),[]
                       //第三种 单个值
                       acc+xxx,0
                       //第四种,如果是字符串
                       acc+xxx,''
                       //第五种,对象
                       acc[val]=xxx,{}
                      )
    最普通的格式
    [xxx].reduce((acc,val)=>{
        操作
        return acc
    },[])
    第一个参数是函数,第二个参数是格式,0/{},[],''
    
    注意当使用concat应该直接return
    [1,2,3,4,[1,2,3]].reduce((acc,val)=>{
      return acc.concat(val)
    },[])
    

    ['beep', 'boop', 'foo', 'bar'], [true, true, false, true]

    //简单的例子
    let arr1 = [1, 2, 3, 4, 5];
    let arr2 = [1, 0, 1, 0, 1];
    
    第一种方法
        let arr3 = [];
        for (let i in arr2) {
          if (arr2[i]) {
            arr3.push(arr1[i])
          }
        }
        console.log(arr3);
    
    第二种方法
    arr1.reduce((acc, item, index) =>
                ( arr2[index] && acc.push(item), acc)
                , []);
    
    观察特点   
    (acc,val,i)=>(操作,acc)   最后返回的是acc
    []   Array.from({length:0})
    [[],[]]   
    有没有想过用 Array.from来实现
    Array.from({length:2}).map(v=>[])
        我们可以知道
        length的值不可能是死的
        如果二维的数组可以是  
        length:Math.max(...arr.map(x=>x.length))
    

    删选出数组中每个数首字母是否含有'b'

    let arr = ['beep', 'boop', 'foo', 'bar'];
    console.log(arr.reduce((acc, val) => (val[0] === 'b' && acc.push(val), acc), []));
    
    进阶   每个数是否含有'b'
    arr.reduce((acc, val) => 
               (val.indexOf('b') >-1 && acc.push(val), acc),
               [])
    

    计算次数

    计算一个数组中某值的次数
    [1, 2, 3, 4, 1, 1, 1, 1, 2, 3, 4].reduce(
      (acc, val) => val === 1? acc + 1 : acc, 0,
    )
    细节解读
    0代表从0开始,acc是迭代的值,默认为0
    
    console.log(['one', 'two', 'three','one', 'two', 'three'].reduce((acc, val) =>
      (acc[val] = (acc[val] || 0) + 1, acc), {},
    ));
    
    细节解读
     (acc[val] = (acc[val] || 0) + 1
      第一次进入的时候 acc[val] 肯定是不存在的所以默认给0,后面给值了就叠加了
      
    升级理解
      计算长度的次数
      console.log(['one', 'two', 'three', 'one', 'two', 'three'].map(v => v.length).reduce(
      (acc, val) =>
        (acc[val] = (acc[val] || 0) + 1, acc), {},
    ));
    

    数组扁平化

    连接两个数组用concat方法
    [1, 2, 3, 4, 5, [1, 3, 4], 5].reduce((acc, val) =>
      acc.concat(val),[]
    );
    
    const flatter=(arr,depth=1)=>
      arr.reduce((acc,val)=>
        acc.concat(depth>1&&Array.isArray(val)?flatter(val,depth-1):val),[]
      );
    console.log(flatter([1,[2,3,4,[2,3,4,[1,2,3]]]],3));
    // 细节 
    &&  做判断
    递归注意是把改变后的值作为参数再次传入函数
    

    查找某个数在数组的位置

    let arr = [1, 2, 3, 4, 1, 2, 1, 3, 1];
    arr.reduce((acc, val, i) =>
      (val === 2 && acc.push(i), acc), [],
    );
    

    字符串操作

    需求在数组的偶数项或者奇数项插入特定的字符
    ['pen', 'pineapple', 'apple', 'pen'].reduce(
      (acc, val, i) =>
        i % 2 === 0 ?
          acc + val + '我'
          : acc + val + '你'
      , '',
    ); //pen我pineapple你apple我pen你
    

    返回数组每一项中最长的那项

    ['this', 'is', 'a', 'testcase'].reduce(
      (acc, val) => 
        	(acc.length > val.length ? acc : val), 0,
    )
    
    // 求和
    [1,2,3,4,5].reduce(
    	(acc,val)=>acc+val,0
    )
    

    把两个数组合并成一个对象

    let arr1 = [1, 2, 3];
    let arr2 = arr1.map(v => v * 3);
    arr1.reduce((acc, val, i) =>
      (acc[val] = arr2[i], acc), {},
    );
    // { '1': 3, '2': 6, '3': 9 }
    

    reduce里面嵌套高阶函数

    可以对数组中的多个对象进行分组

    const partition = (arr, fn) =>
      arr.reduce(
        (acc, val, i, arr) => {
          acc[fn(val, i, arr) ? 0 : 1].push(val);
          return acc;
        },
        [[], []]
      );
    const users = [{ user: 'barney', age: 36, active: false }, { user: 'fred', age: 40, active: true }];
    partition(users, o => o.active); // [[{ 'user': 'fred',    'age': 40, 'active': true }],[{ 'user': 'barney',  'age': 36, 'active': false }]]
    
    用普通函数定义变量
        arr.reduce((acc, val) => {
          let a = val.age;
          acc[a ? 0 : 1].push(val);
          return acc
        },[[],[]]);
    

    复杂的数组交换位置 (底层逻辑暂时不懂,先留着等技术提高了再来解决)

    [1,2,3] =>  每两个数之间交换位置,递归,遍历
    首先判断当数组是两个数,两个数之间交换位置
    const permutations = arr => {
      if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr;
      return arr.reduce(
        (acc, val, i) => {
          //就是这块合并,分解,再遍历
          return acc.concat(
            permutations([...arr.slice(0, i), ...arr.slice(i + 1)])
              .map(item => [val, ...item]),
          );
        }, [],
      );
    };
    console.log(permutations([1, 2, 3, 4]));
    

    对数组进行对象删选再进行属性删选

    const data = [
      {
        id: 1,
        name: 'john',
        age: 24
      },
      {
        id: 2,
        name: 'mike',
        age: 50
      }
    ];
    let obj = ['id', 'name'];
    data.filter(v=>v.age>24)
        .map(item=>
             obj.reduce((acc,val)=>(acc[val]=item[val],acc),{}))
    

    reduce 实现排序

    // 升序
    [0,1,2,3].reduce((acc,val)=>acc-val>=0?acc:val);
    //降序
    [0,1,2,3].reduce((acc,val)=>val-acc>=0?acc:val);
    

    reduce对数组的对象属性进行去重

    let arr = [
      {id: 0, value: 'a'},
      {id: 1, value: 'b'},
      {id: 2, value: 'c'},
      {id: 1, value: 'd'},
      {id: 0, value: 'e'},
    ];
    fn=(a,b)=>a.value===b.value;
    
    console.log(arr.reduce((acc, val) => {
      if (!acc.some(x => fn(val, x))) acc.push(val);
      return acc
    }, []));
    //[ { id: 0, value: 'a' },
    //   { id: 1, value: 'b' },
    //   { id: 2, value: 'c' },
    //   { id: 1, value: 'd' },
    //   { id: 0, value: 'e' } ]
    

    多个数组的每项进行拆成独立的数组

    const unzip = arr =>
      arr.reduce(
        (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),
        Array.from({
          length: Math.max(...arr.map(x => x.length))
        }).map(x => [])
      );
    
    unzip([['a', 1, true], ['b', 2, false]]); // [['a', 'b'], [1, 2], [true, false]]
    

    filter

    取出自身数组不重复的数

    let arr=[1,3,3,4,4,5,6];
    arr.filter((v,i,array)=>array.indexOf(v)==array.lastIndexOf(v))
    
    let arr = [1, 2, 3, 1, 2, 5];
    const fn = (a, b) => a === b;
    console.log(arr.filter((v, i) => arr.every((w, j) => (j === i) === fn(w, v))));
    

    filter筛选出相同或者不同的数

    //第一种方式
    let arr1 = [1, 2, 3, 4, 5];
    let arr2 = [1, 0, 1, 0, 1];
    console.log(arr1.filter(v => !arr2.includes(v)));
    
    //第二种形式
    const intersection = (a, b) => {
      const s = new Set(b);
      return a.filter(x => s.has(x));
    };
    
    intersection([1, 2, 3], [4, 3, 2]); // [2, 3]
    
    //第三种形式
    a中不存在b中的数
    let arr1 = [1, 3, 4, 5, 6, 7,6,6,7,7,20];
    let arr2 = [3, 4, 5, 8, 9, 20, 12];
    console.log(arr1.filter(v => arr2.findIndex(w => w === v) === -1));
    
    如果是小数可以先进行处理再比较
    let arr1 =  [1, 1.2, 1.5, 3, 0];
    let arr2 = [1.9, 3, 0, 3.9];
    console.log(arr1.filter(v => arr2.findIndex(w => Math.round(w)=== Math.round(v)) === -1));
    

    ##############################################################################################.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

  • 相关阅读:
    每周一荐:代码编辑器sublime
    每周一荐:Google的序列化框架Protobuf
    每周一荐:ObjectiveC的开源开发环境GNUstep
    每周一荐:用gnuplot绘制函数曲线
    每周一荐:学习ACE一定要看的书
    临时变量管理器
    每周一荐:TotalCommand的文件夹同步功能
    每周一荐:支持latex的思维导图软件docear
    关于程序员面试的一点想法
    每周一荐:Python Web开发框架Django
  • 原文地址:https://www.cnblogs.com/fangdongdemao/p/10991051.html
Copyright © 2011-2022 走看看