reduce的用法

61 阅读3分钟

语法

reduce(callbackFn, initialValue?) //初始值可选

callbackFn(pre,cur,index,arr)

  • 数组中的每个元素按序执行一个提供的 callbackFn 函数
  • 每一次运行 callbackFn 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值

不提供初始值的情况

1、空数组

 [].reduce((pre,cur)=>{console.log(1111);return pre*cur})

结果:

image.png

2、长度为1

[1].reduce((pre,cur)=>{console.log(1111);return pre*cur})

结果:

image.png

3、长度不为1

[1,3].reduce((pre,cur)=>{console.log(1111);return pre*cur})

结果:

image.png

修改原数组的情况

1、增加元素

[1,2,3].reduce((pre,cur,index,arr)=>{if(index===0){arr.push(4)};return pre+cur},0)

结果:

image.png

2、修改已访问元素

[1,2,3].reduce((pre,cur,index,arr)=>{if(index===1){arr[0]=2};return pre+cur},0)

结果:

image.png

3、修改未访问元素

[1,2,3].reduce((pre,cur,index,arr)=>{if(index===1){arr[2]=2};return pre+cur},0)

结果:

image.png

边界情况

1、数组只有一个元素(不管位置)+未提供初始值

    const arr=new Array(6)
    arr[3]=1
    arr.reduce((pre,cur)=>{console.log(1111);return pre*cur})

结果:

image.png

2、数组为空+提供初始值

[].reduce((pre,cur)=>{console.log(1111);return pre*cur},1)

结果:

image.png

使用场景

  1. 累加累乘
  2. 数据特性分组
  3. 求数组交集,并集,差集
  4. 返回对象指定键值
  5. 树形数据转为数组

使用场景1===>累加累乘

const a = [1, 2, 3, 4, 5]
const getToTal = (array) => {
 return  array.reduce((pre,cur)=>pre+cur,0)
}
const getMul = (array) => {
  return  array.reduce((pre,cur)=>pre*cur,1)
 }
console.log(getToTal(a))
console.log(getMul(a))

使用场景2===>数据特性分组

const objectArray = [
  { id: 1, name: 'Alice', age: 25, occupation: 'Engineer', sex: '男' },
  { id: 2, name: 'Bob', age: 25, occupation: 'Doctor', sex: '女' },
  { id: 3, name: 'Charlie', age: 35, occupation: 'Teacher', sex: '男' },
  { id: 4, name: 'David', age: 40, occupation: 'Lawyer', sex: '男' },
  { id: 5, name: 'Emily', age: 28, occupation: 'Designer', sex: '女' },
  { id: 6, name: 'Frank', age: 40, occupation: 'Developer', sex: '男' }
];
//根据单个属性分类
const groupBySingleKey = (arr, key) => {
  return arr.reduce((pre, cur) => {
    if (!pre[cur[key]]) {
      pre[cur[key]] = [cur];
    } else {
      pre[cur[key]].push(cur);
    }
    return pre;
  }, {});
};

console.log(groupBySingleKey(objectArray, 'age'));

// 生成分类key
const generateKey = (item, key1, key2) => item[key1] + '-' + item[key2];
//根据多个属性分类
const groupByMoreKey = (arr, generateKey) => {
  return arr.reduce((pre, cur) => {
    let key = generateKey(cur, 'age', 'sex');
    if (!pre[key]) {
      pre[key] = [cur];
    } else {
      pre[key].push(cur);
    }
    return pre;
  }, {});
};

使用场景3==>求数组交集,并集、差集

const arr1 = [1, 2, 3, 4, 5];
const arr2 = [2, 4, 6, 8, 10];

// 交集
const getIntersection = (arr1, arr2) => {
  return arr1.reduce((pre, cur) => {
    arr2.includes(cur) && pre.push(cur);
    return pre;
  }, []);
};
console.log(getIntersection(arr1, arr2));

// 并集
const getUnionOfSets = (arr1, arr2) => {
  return arr1.reduce((pre, cur) => {
    !pre.includes(cur) && pre.push(cur);
    return pre;
  }, arr2);
};
console.log(getUnionOfSets(arr1, arr2));

// 差集
const getSetOfDifferences = (arr1, arr2) => {
  const allArr = [...arr1, ...arr2];
  return allArr.reduce((pre, cur) => {
    ((arr1.includes(cur) && !arr2.includes(cur)) || (!arr1.includes(cur) && arr2.includes(cur))) && pre.push(cur);
    return pre;
  }, []);
};
console.log(getSetOfDifferences(arr1, arr2));

使用场景4===>返回对象指定键值

const obj = { a: 1, b: 2, c: 3 };
const getSomeKey = (obj = {}, keys = [], type = 'include') => {
  return Object.keys(obj).reduce((pre, cur) => {
    type === 'include' ? keys.includes(cur) && (pre[cur] = obj[cur]) : !keys.includes(cur) && (pre[cur] = obj[cur]);
    return pre;
  }, {});
};
// console.log(getSomeKey(obj, ['a', 'c']));
// console.log(getSomeKey(obj, ['a', 'c'], 'exclude'));

使用场景5===>树形数据转为数组

const treeData = [
  {
    id: 1,
    title: 'Node 1',
    children: [
      { id: 2, title: 'Node 1.1' },
      { id: 3, title: 'Node 1.2' }
    ]
  },
  {
    id: 4,
    title: 'Node 2',
    children: [
      { id: 5, title: 'Node 2.1' },
      { id: 6, title: 'Node 2.2' }
    ]
  }
];

const treeToArray = (treeData = [], path = []) => {
  return treeData.reduce((pre, cur) => {
    const newPath = [...path, cur.id];
    let curObj = getSomeKey(cur, ['children'], 'exclude');
    curObj.path = newPath;
    return pre.concat(curObj).concat(!!cur.children ? treeToArray(cur.children, newPath) : []);
  }, []);
};

console.log(treeToArray(treeData));