이 글은 js 배열 방식의 축소에 관한 많은 고전적인 코드 조각을 모아서 축소 예시의 사용법을 더 잘 이해하는 데 도움이 될 것입니다.
다음은 제가 직장에서 수집하고 요약한 자바스크립트 배열 메소드 reduce
에 대한 관련 코드 조각입니다. 이 함수가 사용되는 다른 시나리오를 접하게 되면 하나씩 추가하겠습니다. 메모로 되어있습니다. reduce
的相关代码片段,后续遇到其他使用这个函数的场景,将会陆续添加,这里作为备忘。
javascript数组那么多方法,为什么我要单挑reduce
方法,一个原因是我对这个方法掌握不够,不能够用到随心所欲。另一个方面,我也感觉到了这个方法的庞大魅力,在许多的场景中发挥着神奇的作用。
理解reduce
函数
reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值。
arr.reduce([callback, initialValue])
看如下例子:
let arr = [1, 2, 3, 4, 5]; // 10代表初始值,p代表每一次的累加值,在第一次为10 // 如果不存在初始值,那么p第一次值为1 // 此时累加的结果为15 let sum = arr.reduce((p, c) => p + c, 10); // 25 // 转成es5的写法即为: var sum = arr.reduce(function(p, c) { console.log(p); return p + c; }, 10);
片段一:字母游戏
const anagrams = str => { if (str.length <= 2) { return str.length === 2 ? [str, str[1] + str[0]] : str; } return str.split("").reduce((acc, letter, i) => { return acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)); }, []); } anagrams("abc"); // 结果会是什么呢?
reduce
负责筛选出每一次执行的首字母,递归负责对剩下字母的排列组合。
片段二:累加器
const sum = arr => arr.reduce((acc, val) => acc + val, 0); sum([1, 2, 3]);
片段三:计数器
const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0); countOccurrences([1, 2, 3, 2, 2, 5, 1], 1);
循环数组,每遇到一个值与给定值相等,即加1,同时将加上之后的结果作为下次的初始值。
片段四:函数柯里化
函数柯里化的目的就是为了储存数据,然后在最后一步执行。
const curry = (fn, arity = fn.length, ...args) => arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args); curry(Math.pow)(2)(10); curry(Math.min, 3)(10)(50)(2);
通过判断函数的参数取得当前函数的length
(当然也可以自己指定),如果所传的参数比当前参数少,则继续递归下面,同时储存上一次传递的参数。
片段五:数组扁平化
const deepFlatten = arr => arr.reduce((a, v) => a.concat(Array.isArray(v) ? deepFlatten(v) : v), []); deepFlatten([1, [2, [3, 4, [5, 6]]]]);
片段六:生成菲波列契数组
const fibonacci = n => Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []); fibonacci(5);
片段七:管道加工器
const pipe = (...funcs) => arg => funcs.reduce((acc, func) => func(acc), arg); pipe(btoa, x => x.toUpperCase())("Test");
通过对传递的参数进行函数加工,之后将加工之后的数据作为下一个函数的参数,这样层层传递下去。
片段八:中间件
const dispatch = action => { console.log('action', action); return action; } const middleware1 = dispatch => { return action => { console.log("middleware1"); const result = dispatch(action); console.log("after middleware1"); return result; } } const middleware2 = dispatch => { return action => { console.log("middleware2"); const result = dispatch(action); console.log("after middleware2"); return result; } } const middleware3 = dispatch => { return action => { console.log("middleware3"); const result = dispatch(action); console.log("after middleware3"); return result; } } const compose = middlewares => middlewares.reduce((a, b) => args => a(b(args))) const middlewares = [middleware1, middleware2, middleware3]; const afterDispatch = compose(middlewares)(dispatch); const testAction = arg => { return { type: "TEST_ACTION", params: arg }; }; afterDispatch(testAction("1111"));
redux
中经典的compose
函数中运用了这种方式,通过对中间件的重重层叠,在真正发起action的时候触发函数执行。
片段九:redux-actions对state的加工片段
// redux-actions/src/handleAction.js const handleAction = (type, reducer, defaultState) => { const types = type.toString(); const [nextReducer, throwReducer] = [reducer, reducer]; return (state = defaultState, action) => { const { type: actionType } = action; if (!actionType || types.indexOf(actionType.toString()) === -1) { return state; } return (action.error === true ? throwReducer : nextReducer)(state, action); } } // reduce-reducers/src/index.js const reduceReducer = (...reducers) => { return (previous, current) => { reducers.reduce((p, r) => r(p, current), previous); } } // redux-actions/src/handleActions.js const handleActions = (handlers, defaultState, { namespace } = {}) => { // reducers的扁平化 const flattenedReducerMap = flattenReducerMap(handles, namespace); // 每一种ACTION下对应的reducer处理方式 const reducers = Reflect.ownkeys(flattenedReducerMap).map(type => handleAction( type, flattenedReducerMap[type], defaultState )); // 状态的加工器,用于对reducer的执行 const reducer = reduceReducers(...reducers); // reducer触发 return (state = defaultState, action) => reducer(state, action); }
片段十:数据加工器
const reducers = { totalInEuros: (state, item) => { return state.euros += item.price * 0.897424392; }, totalInYen: (state, item) => { return state.yens += item.price * 113.852; } }; const manageReducers = reducers => { return (state, item) => { return Object.keys(reducers).reduce((nextState, key) => { reducers[key](state, item); return state; }, {}) } } const bigTotalPriceReducer = manageReducers(reducers); const initialState = { euros: 0, yens: 0 }; const items = [{ price: 10 }, { price: 120 }, { price: 1000 }]; const totals = items.reduce(bigTotalPriceReducer, initialState);
片段十一:对象空值判断
let school = { name: 'Hope middle school', created: '2001', classes: [ { name: '三年二班', teachers: [ { name: '张二蛋', age: 26, sex: '男', actor: '班主任' }, { name: '王小妞', age: 23, sex: '女', actor: '英语老师' } ] }, { name: '明星班', teachers: [ { name: '欧阳娜娜', age: 29, sex: '女', actor: '班主任' }, { name: '李易峰', age: 28, sex: '男', actor: '体育老师' }, { name: '杨幂', age: 111, sex: '女', actor: '艺术老师' } ] } ] }; // 常规做法 school.classes && school.classes[0] && school.classes[0].teachers && school.classes[0].teachers[0] && school.classes[0].teachers[0].name // reduce方法 const get = (p, o) => p.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), o); get(['classes', 0, 'teachers', 0, 'name'], school); // 张二蛋
片段十二:分组
const groupBy = (arr, func) => arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => { acc[val] = (acc[val] || []).concat(arr[i]); return acc; }, {}); groupBy([6.1, 4.2, 6.3], Math.floor); groupBy(['one', 'two', 'three'], 'length');
首先通过map
计算出所有的键值,然后再根据建值进行归类
片段十三:对象过滤
const pick = (obj, arr) => arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
根据给出的键值来遍历,比较对象中是否存在相同键值的的值,然后通过逗号表达式把赋值后的对象赋给下一个的初始值
片段十四:数组中删除指定位置的值
const remove = (arr, func) => Array.isArray(arr) ? arr.filter(func).reduce((acc, val) => { arr.splice(arr.indexOf(val), 1); return acc.concat(val); }, []) : []; const arr = [1, 2, 3, 4]; remove(arr, n => n % 2 == 0);
首先根据filter
函数过滤出数组中符合条件的值,然后使用reduce
reduce
메서드를 선택하는 이유 중 하나는 내가 원하는 대로 사용할 만큼 이 메서드에 대해 충분히 알지 못하기 때문입니다. 한편으로는 많은 장면에서 마법 같은 역할을 하는 이 방식의 큰 매력도 느낍니다. reduce
함수 이해하기reduce() 메서드는 함수를 누산기(accumulator)로 받아들이고 배열의 각 값(왼쪽에서 오른쪽으로)이 감소하기 시작하여 최종적으로 값이 됩니다. .
const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); const delay = d => new Promise(r => setTimeout(r, d)); const print = args => new Promise(r => r(args)); runPromisesInSeries([() => delay(1000), () => delay(2000), () => print('hello')]);다음 예를 살펴보세요.
const orderBy = (arr, props, orders) => [...arr].sort((a, b) => props.reduce((acc, prop, i) => { if (acc === 0) { const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]]; acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0; } return acc; }, 0) ); const users = [{ name: 'fred', age: 48 }, { name: 'barney', age: 36 }, { name: 'fly', age: 26 }]; orderBy(users, ['name', 'age'], ['asc', 'desc']); orderBy(users, ['name', 'age']);Fragment 1: Alphabet Game
const select = (from, selector) => selector.split('.').reduce((prev, cur) => prev && prev[cur], from); const obj = { selector: { to: { val: 'val to select' } } }; select(obj, 'selector.to.val');
reduce
는 각 실행의 첫 글자를 필터링하는 역할을 담당하고 재귀는 배열을 담당합니다. 그리고 남은 글자들을 합쳐보세요. Fragment 2: Accumulator
rrreee
rrreee 값이 주어진 값과 동일할 때마다 1이 추가되고 후속 결과가 추가됩니다. 다음번의 초기값으로.
함수 커링의 목적은 데이터를 저장한 후 마지막 단계에서 실행하는 것입니다. rrreee
함수 매개변수를 판단하여 현재 함수의길이
를 가져옵니다. (물론 직접 지정할 수도 있습니다.) 전달된 매개변수가 현재 매개변수보다 작으면 아래 재귀를 계속하세요. 그리고 지난번에 전달된 매개변수를 저장합니다. 조각 5: 배열 병합🎜🎜🎜rrreee🎜🎜🎜조각 6: Fiboletchi 배열 생성🎜🎜🎜rrreee🎜🎜🎜조각 7: 파이프 프로세서🎜🎜🎜rrreee🎜By 전달된 매개변수 처리 기능 처리 후 처리된 매개변수 데이터는 다음 함수의 매개변수로 사용되며 레이어별로 전달됩니다. 🎜🎜🎜🎜조각 8: 미들웨어 🎜🎜🎜rrreeeredux
는 클래식 compose
함수에서 이 메서드를 사용합니다. 미들웨어 트리거 기능의 레이어입니다. 작업이 실제로 시작될 때 실행됩니다. 🎜
🎜🎜Fragment 9: Redux-actions 상태 처리 🎜🎜🎜rrreee
🎜🎜Fragment 10: 데이터 프로세서🎜🎜🎜rrreee
🎜🎜Fragment 11: 객체 null 값 판단🎜🎜🎜rrreee
🎜🎜Fragment 12: Grouping🎜🎜🎜rrreee
첫 번째 패스 맵
모든 키 값을 계산한 후 생성된 값에 따라 정렬합니다🎜
🎜🎜Fragment 13: 객체 필터링🎜🎜🎜rrreee🎜주어진 키 값에 따라 탐색하고 값이 있는지 비교합니다. 객체에 동일한 키 값을 사용하고 쉼표 표현식을 통해 할당된 객체를 다음 초기 값에 할당합니다🎜🎜🎜🎜Fragment 14: 배열의 지정된 위치에서 값을 삭제합니다🎜🎜🎜rrreee🎜 먼저 필터링합니다. filter
함수에 따라 배열의 정규화된 값을 삭제한 다음 reduce
를 사용하여 원래 배열의 정규화된 값을 삭제한다는 결론을 내릴 수 있습니다. arr의 최종 값은 [1, 3]🎜🎜🎜🎜Fragment 15: Promise가 순서대로 실행됩니다🎜🎜🎜rrreee🎜🎜🎜Fragment 16: Sorting🎜🎜🎜rrreee🎜🎜🎜Fragment 17: Selection🎜🎜 🎜rrreee🎜The 이상이 제가 정리한 내용입니다. 여러분, 앞으로 모든 분들께 도움이 되었으면 좋겠습니다. 🎜🎜관련 기사: 🎜🎜🎜 Vue가 패키징 도구를 구성하는 방법에 대한 자세한 설명 🎜🎜🎜🎜 vue에서 데이터 변경을 자동으로 감지하는 watch 구현 방법 🎜🎜🎜🎜 로딩 권한 관리 모듈 구현 방법(자세한 튜토리얼) 🎜🎜 🎜🎜 vue2에서 통신을 구현하는 방법은 무엇입니까? 🎜🎜🎜🎜Angular 2+🎜🎜에서 스타일 바인딩 방법은 무엇입니까?
위 내용은 js 배열 감소 관련 사용법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!