Use and difference between JS array Map and reduce (using Map type)

preface

Today, I encountered a data processing problem. Although it was solved, the process seems very cumbersome, the code is not elegant, and the logic is very cumbersome. With reduce, it can be easily solved and beautiful. Let's learn about reduce first, and then give an example of how to use reduce and its difference from map

I Use of reduce

1. Grammar

arr.reduce(callback,[initialValue])

Reduce executes the callback function for each element in the array in turn, excluding the elements deleted or never assigned in the array. It accepts four parameters: initial value (or the return value of the previous callback function), current element value, current index and the array calling reduce.

callback (Function that executes each value in the array, including four parameters)
    1,previousValue (The value returned by the last call callback, or the initial value provided( initialValue))
    2,currentValue (Elements currently being processed in the array)
    3,index (Index of the current element in the array)
    4,array (call reduce (array of)

initialValue (As the first call callback (first parameter of.)

2. Instance resolves the initialValue parameter

First example:

var arr = [2, 1, 4, 5];
var sum = arr.reduce((prev, cur, index, arr)=>{
    console.log(prev, cur, index);
    return prev + cur;
})
console.log(arr, sum);

Print results:
2 1 1
3 4 2
7 5 3
[2, 1, 4, 5] 12

It can be seen that the index in the above example starts from 1, and the value of the first prev is the first value of the array. The array length is 4, but the reduce function loops 3 times.

Look at the second example:

var arr = [2, 1, 4, 5];
var sum = arr.reduce((prev, cur, index, arr)=> {
    console.log(prev, cur, index);
    return prev + cur;
},0) //Note that the initial value is set
console.log(arr, sum);

Print results:
0 2 0
2 1 1
3 4 2
7 5 3
[2,1,4,5] 12

In this example, the index starts from 0. The value of prev for the first time is the initial value we set, 0. The array length is 4. The reduce function loops 4 times.

Conclusion: if initialValue is not provided, reduce will execute the callback method from index 1 and skip the first index. If initialValue is provided, start with index 0.

3. Simple usage of reduce

3.1 summation and accumulation
var  arr = [1, 2, 3, 4];
var sum = arr.reduce((x,y)=>x+y)
var mul = arr.reduce((x,y)=>x*y)
console.log( sum ); //Summation, 10
console.log( mul ); //Product, 24
3.2 calculate the number of occurrences of each element in the array
let names = ['1', '1', '2', '2', '3','1'];

let nameNum = names.reduce((pre,cur)=>{
  if(cur in pre){
    pre[cur]++
  }else{
    pre[cur] = 1 
  }
  return pre
},{})
console.log(nameNum); //{"1":3,"2":2,"3":1}
3.3 array de duplication
let arr = [1,2,3,4,4,1]
let newArr = arr.reduce((pre,cur)=>{
    if(!pre.includes(cur)){
      return pre.concat(cur)
    }else{
      return pre
    }
},[])
console.log(newArr);// [1, 2, 3, 4]
3.4 converting a two-dimensional array to a one-dimensional array
let arr = [[0, 1], [2, 3], [4, 5]]
let newArr = arr.reduce((pre,cur)=>{
    return pre.concat(cur)
},[])
console.log(newArr); // [0, 1, 2, 3, 4, 5]
3.5 convert multidimensional array to one dimension
let arr = [[0, 1], [2, 3], [4,[5,6,7]]]
const newArr = function(arr){
   return arr.reduce((pre,cur)=>pre.concat(Array.isArray(cur)?newArr(cur):cur),[])
}
console.log(newArr(arr)); //[0, 1, 2, 3, 4, 5, 6, 7]
3.6 attribute summation in object (the most applicable business of reduce)
var result = [
    {
        subject: 'math',
        score: 10
    },
    {
        subject: 'chinese',
        score: 20
    },
    {
        subject: 'english',
        score: 30
    }
];

var sum = result.reduce(function(prev, cur) {
    return cur.score + prev;
}, 0);
console.log(sum) //60

II Map type

1. Basic concept of map

Map saves a key value pair, and any value or key is used as a key or value. Different from the [value,value] form of elements in Set, the form of elements in map is [key,value]

Note: if the reference type data is used as the key name, it should be noted that when obtaining the key value pair, the reference type data with the same address should be passed instead of simple same value data.

2. Properties of map

  • map. Size: number of elements in the map

3.Map method

3.1 creation and addition
  • Constructor passed in array creation
  • Create a Map object using a Set object
  • map.set(key, value) adds a key value pair record, and then returns the map object
3.2 deletion
  • map.delete(key) returns true if the key exists, and false if the element does not exist
  • map.clear() removes all key / value pairs from the Map object
3.3 query and traversal
  • map.has(key) returns true if the key exists; otherwise, returns false
  • map.get(key): if the key exists, return the value corresponding to the key; otherwise, return undefined
  • map.entries() returns a new iterator object, which contains an array of elements in the form of [key, value] according to the insertion order
  • map.keys() returns a new iteratable object containing the keys of the map in the insertion order
  • map.values() returns a new iteratable object containing the values of the map in the insertion order
  • map. Foreach ((value, key, map) = > {}) where value is the value of the current element, key is the key name of the current element, and map is the map object currently being traversed

III Case insights

The original data is like this (because it is too long, only part of the data is pasted)
Objective: to add the value s of the same grade and screen them according to the month and grade

const data = {
  "visionList": [
    {
      "gradeId": "1",
      "checkResult": "A",
      "quarter": "9",
      "value": "14"
    },
    {
      "gradeId": "1",
      "checkResult": "B",
      "quarter": "9",
      "value": "7"
    },
   ]
  }

processing method

const getData=(data,firstGradeId,lastGradeId,checkResult)=>{
   const midData =  data.visionList.filter(item=>{
        return item.quarter>=firstGradeId||item.quarter<=lastGradeId
    }).filter(i =>{
        return i.checkResult == checkResult
    })

    let gradeArr =[...new Set(data.visionList.map(item=>{
        return item.gradeId
    }))]

    let gradeObject={}

    gradeArr.map(item =>{
        midData.map(i =>{
            if(i.gradeId ==item){
                gradeObject={
                    ...gradeObject,
                    [item]:gradeObject?.[item]?.length>0?[...gradeObject[item],i]:[i]
                }
            }
        })
    })
}

After this processing, although the goal can be achieved, but because it is too heavy, it is not only one step away from the goal, but also the code is very unsightly. Let's take a look at the results after using the reduce method.

1. Use reduce to process data

Use the combination of reduce and Map types to process data

  let res = new Map()
  
  const midData = data.reduce((pre=[],item) =>{
      if(res.has(item.gradeId)){
          res.get(item.gradeId).value =String(+res.get(item.gradeId).value + +item.value)
      }else{
          let a = {...item}
          pre.push(a)
          res.set(item.gradeId,a)
      }
      return pre
  },[])

  console.log(midData)
  

Printed results:

2. Use the map method to process the above data

let res1 = new Map()
let list =[]
const result = data.map(item=>{
  if(res1.has(item.gradeId)){
          res1.get(item.gradeId).value =String(+res1.get(item.gradeId).value + +item.value)
    }else{
          let a = {...item}
          list=[...list,a]
          res1.set(item.gradeId,a)
    }
})
console.log(list)

Conclusion: the results as like as two peas are identical, the code is slightly different. Map needs to define list first and then receive the return. Reduce already has the pre parameter, and the second parameter of reduce can define the type of pre at any time. Of course, generally, the map that can be solved by reduce can be solved. There are many roads to success, but there is always one way that is the shortest way, or maybe reduce() is even higher

Keywords: Javascript Front-end

Added by chito on Sat, 15 Jan 2022 00:12:10 +0200