>웹 프론트엔드 >JS 튜토리얼 >js 배열 감소 관련 사용법

js 배열 감소 관련 사용법

亚连
亚连원래의
2018-06-13 14:24:361633검색

이 글은 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(&#39;action&#39;, 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: &#39;Hope middle school&#39;,
 created: &#39;2001&#39;,
 classes: [
  {
   name: &#39;三年二班&#39;,
   teachers: [
    { name: &#39;张二蛋&#39;, age: 26, sex: &#39;男&#39;, actor: &#39;班主任&#39; },
    { name: &#39;王小妞&#39;, age: 23, sex: &#39;女&#39;, actor: &#39;英语老师&#39; }
   ]
  },
  {
   name: &#39;明星班&#39;,
   teachers: [
    { name: &#39;欧阳娜娜&#39;, age: 29, sex: &#39;女&#39;, actor: &#39;班主任&#39; },
    { name: &#39;李易峰&#39;, age: 28, sex: &#39;男&#39;, actor: &#39;体育老师&#39; },
    { name: &#39;杨幂&#39;, age: 111, sex: &#39;女&#39;, actor: &#39;艺术老师&#39; }
   ]
  }
 ]
};
// 常规做法
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([&#39;classes&#39;, 0, &#39;teachers&#39;, 0, &#39;name&#39;], school); // 张二蛋

片段十二:分组

const groupBy = (arr, func) =>
arr.map(typeof func === &#39;function&#39; ? 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([&#39;one&#39;, &#39;two&#39;, &#39;three&#39;], &#39;length&#39;);

首先通过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

JavaScript 배열에는 메서드가 너무 많습니다. 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(&#39;hello&#39;)]);

다음 예를 살펴보세요.

const orderBy = (arr, props, orders) =>
 [...arr].sort((a, b) =>
  props.reduce((acc, prop, i) => {
   if (acc === 0) {
    const [p1, p2] = orders && orders[i] === &#39;desc&#39; ? [b[prop], a[prop]] : [a[prop], b[prop]];
    acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
   }
   return acc;
  }, 0)
 );
const users = [{ name: &#39;fred&#39;, age: 48 }, { name: &#39;barney&#39;, age: 36 }, { name: &#39;fly&#39;, age: 26 }];
orderBy(users, [&#39;name&#39;, &#39;age&#39;], [&#39;asc&#39;, &#39;desc&#39;]); 
orderBy(users, [&#39;name&#39;, &#39;age&#39;]);
Fragment 1: Alphabet Game

const select = (from, selector) =>
 selector.split(&#39;.&#39;).reduce((prev, cur) => prev && prev[cur], from);
const obj = { selector: { to: { val: &#39;val to select&#39; } } };
select(obj, &#39;selector.to.val&#39;);
reduce는 각 실행의 첫 글자를 필터링하는 역할을 담당하고 재귀는 배열을 담당합니다. 그리고 남은 글자들을 합쳐보세요.

Fragment 2: Accumulator

rrreee

Fragment 3: Counter

rrreee 값이 주어진 값과 동일할 때마다 1이 추가되고 후속 결과가 추가됩니다. 다음번의 초기값으로.

조각 4: 함수 커링

함수 커링의 목적은 데이터를 저장한 후 마지막 단계에서 실행하는 것입니다. rrreee

함수 매개변수를 판단하여 현재 함수의 길이를 가져옵니다. (물론 직접 지정할 수도 있습니다.) 전달된 매개변수가 현재 매개변수보다 작으면 아래 재귀를 계속하세요. 그리고 지난번에 전달된 매개변수를 저장합니다.

조각 5: 배열 병합🎜🎜🎜rrreee🎜🎜🎜조각 6: Fiboletchi 배열 생성🎜🎜🎜rrreee🎜🎜🎜조각 7: 파이프 프로세서🎜🎜🎜rrreee🎜By 전달된 매개변수 처리 기능 처리 후 처리된 매개변수 데이터는 다음 함수의 매개변수로 사용되며 레이어별로 전달됩니다. 🎜🎜🎜🎜조각 8: 미들웨어 🎜🎜🎜rrreee

redux는 클래식 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.