[JS] map filter reduce

39527 ワード

  const products = [
    {name: '반팔티', price: 15000},
    {name: '긴팔티', price: 20000},
    {name: '핸드폰케이스', price: 15000},
    {name: '후드티', price: 30000},
    {name: '바지', price: 25000}
  ];

map


map()は、アレイ内の各要素に対して所定の関数を呼び出す結果を収集する.🔔新しい配置を返します.
arr.map(callback(currentValue[, index[, array]])[, thisArg])

  • callback:新しい配列要素を生成する関数を持つ3つの引数.
    (1)currentValue:処理する現在の要素
    (2)index:処理する現在の要素のインデックス
    (3)array:map()を呼び出す配列

  • thisArg:callbackの実行時にこの値として使用される値
  • 🔧 rObj{}上obj.keyをkey値objとする.valueをvalue値に整理し、各要素を順次ロードして、新しい配列を戻り値として返します.
    var kvArray = [{key:1, value:10},
                   {key:2, value:20},
                   {key:3, value: 30}];
    
    var reformattedArray = kvArray.map(function(obj){
       var rObj = {};
       rObj[obj.key] = obj.value;	
       return rObj;
    });
    // reformattedArray는 [{1:10}, {2:20}, {3:30}]
    
    // kvArray는 그대로
    // [{key:1, value:10},
    //  {key:2, value:20},
    //  {key:3, value: 30}]
    🔧 mapの動作原理
    
    // f iter를 인자로 받고 f를 a인자를 받는 함수화시켜서 결과값을 res에 담는다
    const map = (f, iter) => {
    let res = [];
    for (const a of iter){
    	res.push(f(a));
    }
      return res;
    };
    
    
    let names = [];
    for (const p of products){
    	names.push(p.name);
    }
    log(name);
    
    log(map(p=>p.name, products));	// products에 있는 name들 출력
    
    
    
    let prices = [];
    for (const p of products){
    	names.push(p.price);
    }
    log(name);
    
    log(map(p=>p.price, products));	// products에 있는 price들 출력
    map関数は、反復器プロトコルに従う関数を使用することができる.
    
    function *gen(){
    	yield 2;
      	yield 3;
      	yield 4;
    }
    log(map((a => a*a, gen());
    // [4,9,16]
            
            
    let m = new Map();
        m.set('a',10);
    	m.set('b',20);
    map(([k,a]=>[k,a*2]), m);	// ["a",20],["b",40]
    
    const it = m[Symbol.iterator]();
    log(it.next());	// value:Array(2) ["a",10]	
    log(it.next());	// value:Array(2) ["b",20]	

    filter


    filter()は、所与の関数でテストされたすべての要素を収集します.🔔新しい配列に戻ります.
    arr.filter(callback(element[, index[, array]])[, thisArg])

  • コールバック:各要素の関数をテストします.trueが戻ると要素が保持され、falseが戻ると3つのパラメータが破棄されます.
    (1)element:処理する現在の要素
    (2)index:処理する現在の要素のインデックス
    (3)array:filter()を呼び出す配列

  • thisArg:callbackを実行するときに使用する値
  • 🔧 indexOfは、配列内で指定した要素を検索できる最初のインデックスを返し、存在しない場合は-1を返します.
    const fruits = ['apple', 'banana', 'grapes', 'mango', 'orange'];
    
    /**
     * 검색 조건에 따른 배열 필터링(쿼리)
     */
    const filterItems = (query) => {
      return fruits.filter((el) =>
        el.toLowerCase().indexOf(query.toLowerCase()) > -1
      );
    }
    
    console.log(filterItems('ap')); // ['apple', 'grapes']
    console.log(filterItems('an')); // ['banana', 'mango', 'orange']
    🔧 フィルタの動作原理
    const filter = (f, iter) =>{
    	let iter = [];
      for (const p of iter){
      	if(f(a)) res.push(a);
      }
    }
    
    
    let under20000 = [];
    for (const p of products) {
    	if(p.price < 20000) under20000.push(p);
    }
    log(...under20000); // 반팔티, 핸드폰케이스
    
    log(...filter(p=>p.price < 20000, products)); // 반팔티, 핸드폰케이스
    
    let over20000 = [];
    for (const p of products) {
    	if(p.price >= 20000) over20000.push(p);
    }
    log(...over20000); // 긴팔티, 후드티, 바지
    log(...filter(p=>p.price >= 20000, products)); // 긴팔티, 후드티, 바지

    reduce


    reduce()は、アレイ内の各要素に対して所定のreducer関数を実行し、結果値を返します.
    arr.reduce(callback[, initialValue])
    reducer関数には4つの因子がある.
    1.アキュムレータ(acc)-アキュムレータにreducer関数の戻り値を割り当てて保持するため、最終結果は値です.
    2.現在値(cur)
    3.現在のインデックス(idx)
    4.元のシナリオ(src)
    arr.reduce(function(acc,cur,idx,src)){
               return acc + cur;
               }
    🔧 reduceが理解しにくい例
  • MDN reduce
  • var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
    
    var countedNames = names.reduce(function (allNames, name) {
      if (name in allNames) {
        allNames[name]++;
      }
      else {
        allNames[name] = 1;
      }
      return allNames;
    }, {});
    // countedNames is:
    // { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
    好奇心のあるところ
    [原句]どうして中にいるの?
    2.allNames[name]がallNamesによって配列されている場合、順番に配列されているのではないでしょうか.
    解決する
    1.関数の後ろにある{}は、名前を初期値で積み重ねたallNameです.
    2.allNamesは順番に1つずつ中に入れるのではなく、{}の形で1つずつ中に積み上げられています.
    したがってallNames[name]はvalueであり、nameはkeyである.
    AllName、nameのコンソール.ログ結果値
    {} Alice
    { Alice: 1 } Bob
    { Alice: 1, Bob: 1 } Tiff
    { Alice: 1, Bob: 1, Tiff: 1 } Bruce
    { Alice: 1, Bob: 1, Tiff: 1, Bruce: 1 } Alice
    { Alice: 2, Bob: 1, Tiff: 1, Bruce: 1 }
    🔧 reduceの動作原理
    const nums = [1,2,3,4,5];
    
    let total = 0;
    for (const n of nums) {
    	total = total + n;
    }
    log(total)
    
    const reduce = (f, acc, iter) => {
    	// iter 값이 없다면
      if(!iter){
        iter = acc[Symbol.iterator]();	// iterable
          acc = iter.next().value;	// 다음 값을 초기값으로
        }
      for (const a of iter){
        acc = f(acc,a);
        }
      	return acc;
    }
    
    const add = (a,b) => a + b;
    log(reduce(add, 0, [1,2,3,4,5]));	// 15
    >> log(add(add(add(add(0,1),2),3),4),5); //15
    
    log(reduce(add, [1,2,3,4,5])); 처럼 초기값을 두지 않는다면
    log(reduce(add, 1, [2,3,4,5])); reduce가 내부적으로 값을 이와 같이 받은것처럼 동작한다.
    
    
    log(reduce((total_price, product) => total_price + product.price, 0, products));	// 105000

    map+filter+reduce


    🔧 製品内の20000未満のフィルタ値(配列)をmapとして抽出し、reduceが追加した値を返します.
    const add = (a+b) => a + b;
    log(reduce(add,
               map(p=>p.price,
                   filter(p=>p.price < 20000, products))));
    // 30000
    🔧 mapで製品中の価格値(配列)を抽出した後、フィルタリングされた20000未満の価格を割引加算値に戻します.
    以上の結果値は同じです.
    const add = (a+b) => a + b;
    log(reduce(add,
               filter(n=>n<20000,
                   map(p=>p.price, products))));
    // 30000
    画像のソース