There are some JavaScript array methods that I don’t know if you’ve ever teased

  • Why only forward lookupfind,findIndexAnd theNo reverse lookupthelastFind,lastFindIndex
  • Why not?Query all index methods that meet the criteria findIndexs
  • Why did I want to delete some index values in the array, but did not delete correctlydelByIndexsmethods
  • Why is there no addition, subtraction, multiplication and division
  • .
  • why

Yes, it doesn’t, but there are methods that can help us implement these functions. Ok, let’s use actions to retrieve the missing love of arrays, to enhance the flexibility of our project to control arrays. Let’s begin.

Reverse query index – lastFindIndex

We know that findIndex: starts the query from index 0 forward, but not backward

const list = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }]
list.findIndex(i= > i.id == 3)/ / 2
list.findIndex(i= > i.id == 33)/ / 1
Copy the code

Implement our lastFindIndex method against findIndex. In case the name is still the same, it is not recommended to extend the method directly on the prototype. Let’s implement it ourselves

const lastFindIndex = function (arr, cb) {
    // Clone in reverse order
    const list = arr.slice().reverse()
    // Use the existing forward lookup method findIndex to query
    const index = list.findIndex(cb)
    // List. Length-1 is the last index of the array
    return index === -1 ? -1: list.length - 1 - index
}
const list = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 3 }, { id: 7 }]
lastFindIndex(list, i= > i.id == 3) / / 5
lastFindIndex(list, i= > i.id == 33) // -1
Copy the code

Reverse lookup value – lastFind

Find also starts at index 0 and returns on index 0, undefined on index 0, but does not have a reverse lookup method

const list = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 3 }, { id: 7 }]
list.find(i= > i.id == 3) //{id: 3}
list.find(i= > i.id == 33) // undefined
Copy the code

To implement our lastFind against find, let’s implement it ourselves

const lastFind = function (arr, cb) {
    return arr.slice().reverse().find(cb)
}
const list = [
    { type: 1.subType: 11 },
    { type: 2.subType: 22 },
    { type: 3.subType: 33 },
    { type: 4.subType: 44 },
    { type: 5.subType: 55 },
    { type: 3.subType: 34 },
    { type: 7.subType: 77 }
]
list.find(i= > i.type == 3) //{type: 3, subType: 33}
lastFind(list, i= > i.type == 3) //{type: 3, subType: 34}
lastFind(list, i= > i.type == 33) //undefined
Copy the code

If you want to find all of them, you can use filter

Query all indexes that meet the criteria – findIndexs

  • Sometimes, you want to get all the indexes of the values in the array that meet the criteria, becausefindIndexYou can only return one, so you’re like… If only it would turn up
const findIndexs = function (arr, cb) {
    const ret = []
    for (let i = 0; i < arr.length; i++) {
        if (cb(arr[i])) {
            ret.push(i)
        }
    }
    return ret
}
const list = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }]
findIndexs(list, i= > [2.4.7].includes(i.id)) / / [1, 3, 6]
Copy the code

Delete array multiple values – delByIndexs

  • Sometimes, you want to get all the index values that meet the condition, and you want to delete the corresponding index value, but the positive deletion will change the array length, so that the later deleted values do not match, so you want to delete the index value. And then came

No corresponding example is as follows:

const delIndexs = [1.3.6]
const list = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }]
delIndexs.forEach(i= > {
    list.splice(i, 1)})/ / I = 1, delete right now array = > [{id: 1}, {id: 3}, {id: 4}, {id: 5}, {id: 6}, {id: 7}]
/ / I = 3, delete right now array = > [{id: 1}, {id: 3}, {id: 4}, {id: 6}, {id: 7}]
/ / I = 6, delete right now array = > [{id: 1}, {id: 3}, {id: 4}, {id: 6}, {id: 7}]
Index 6 cannot be found because the array length has changed

/ / array eventually become = > [{id: 1}, {id: 3}, {id: 4}, {id: 6}, {id: 7}]

// 但是我们的预期是:[{ id: 1 }, { id: 3 },  { id: 5 }, { id: 6 }]
Copy the code

DelByIndexs implementation idea is as follows, delete from the back to the front must be correct, emM…

const delByIndexs = function (arr, delIndexs,isDeep = true) {
    // Whether to clone, sometimes you do not want to affect the original array, need to clone
    if(isDeep) arr = JSON.Parse(JSON.stringify(arr))
    // Sort first in descending order, delete from back to front
    delIndexs = delIndexs.sort((a, b) = > b - a)
    for (let i = 0; i < delIndexs.length; i++) {
        arr.splice(delIndexs[i], 1)}return arr
}

const list = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }]

// findIndexs is implemented above to query all values that meet the criteria
const delIndexs = findIndexs(list, i= > [2.4.7].includes(i.id)) / / [1, 3, 6]

delByIndexs(list, delIndexs) // [{ id: 1 }, { id: 3 }, { id: 5 }, { id: 6 }]
Copy the code

ArrayRepeat – arrayRepeat

String has a repeat method, array does not have a problem, we create our own

/ * * *@description: Array copy *@param {Array} Arr: Array to copy *@param {Number} N: indicates the number of replication times. The default value is 0 */
const arrayRepeat = function(arr, n = 0) {
    let base = 0
    let res = arr
    while (base < n) {
        res = res.concat(arr)
        base++
    }
    return res
}
arrayRepeat([1.2.3]) // [1, 2, 3] No copy times By default, no copy is returned
arrayRepeat([1.2.3].1) // [1, 2, 3, 1, 2, 3
arrayRepeat([1.2.3].2) // [1, 2, 3, 1, 2, 3, 1, 2, 3
arrayRepeat([1.2.3].3) // [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3
arrayRepeat([{ name: 'lisi'}].1) // [{name: "lisi"},{name: "lisi"}
Copy the code

Array interception – arraySubstr

Substr = substr = substr = substr = substr = substr = substr = substr = substr = substr = substr = substr = substr = substr = substr = substr = substr = substr = substr = substr = substr

/ * * *@description: Make arrays have the same functionality as string substr *@param { Array } Arr: array *@param { Number } StartIndex: indicates the startIndex value *@param { Number} Len: Truncated length */
function arraySubstr(arr, startIndex, len) {
    return arr.slice(startIndex, startIndex + len)
}
let arr = [1.2.3.4.5]

arraySubstr(arr, 0.1) / / [1]
arraySubstr(arr, 0.2) / / [1, 2]
arraySubstr(arr, 0.3) / / [1, 2, 3]
arraySubstr(arr, 1.3) / / / 2 and 4

'12345'.substr(0.1) / / '1'
'12345'.substr(0.2) / / '12'
'12345'.substr(0.3) / / '123'
'12345'.substr(1.3) / / '234'
Copy the code

Array value access – arrayAt

I don’t know if you’ve heard of the array.prototype. at method, but it’s already implemented in Google, and it’s not very compatible. If you want to use it right away, you can write your own. But sometimes we want to access elements from the end, not the beginning. For example, to access the last element of an array:

const arr = [1.2.3.4.5]
// The last item in the array
const lastItem = arr[ arr.length - 1]
Copy the code

Arr [arr.length-1] is the way to access the last element of the array, where arr.length-1 is the index of the last element. The problem is that square bracket accessors do not allow items to be accessed directly from the end of the array, nor do they accept negative subscripts.

Thus, a new proposal (phase 3 as of January 2021) introduces the at() method to arrays (as well as typed arrays and strings) and addresses many of the limitations of square bracket accessors.

What? Proposal 21? It’s easy to realize one by ourselves. Don’t be afraid!

/ * * *@description: Accesses the element * based on the index@param { Array } Arr: array *@param { Number } Index: indicates the index. The default value is 0 */
const arrayAt = function (arr, index = 0) {
    // Array length
    const len = arr.length
    return index < 0 ? arr[len + index] : arr[index]
}
// Google Chrome test, if your Browser doesn't work, it's probably not up to date
[1.2.3.4].at() / / 1
[1.2.3.4].at(1) / / 2
[1.2.3.4].at(2) / / 3
[1.2.3.4].at(3) / / 4
[1.2.3.4].at(4) // undefined

[1.2.3.4].at(-1) / / 4
[1.2.3.4].at(-2) / / 3
[1.2.3.4].at(-3) / / 2
[1.2.3.4].at(-4) / / 1
[1.2.3.4].at(-5) // undefined

arrayAt([1.2.3.4]) / / 1
arrayAt([1.2.3.4].1) / / 2
arrayAt([1.2.3.4].2) / / 3
arrayAt([1.2.3.4].3) / / 4
arrayAt([1.2.3.4].4) // undefined

arrayAt([1.2.3.4],-1) / / 4
arrayAt([1.2.3.4],-2) / / 3
arrayAt([1.2.3.4],-3) / / 2
arrayAt([1.2.3.4],-4) / / 1
arrayAt([1.2.3.4],-5) // undefined
Copy the code

StringAt, we’re going to skip over it

/ * * *@description: Accesses an index value * of the string based on the index@param { String } str
 * @param { Number } Index: indicates the index. The default value is 0 */
const stringAt = function (str, index = 0) {
    // String length
    const len = str.length
    return index < 0 ? str[len + index] : str[index]
}
Copy the code

Basic group – group

Arrays do not have grouping methods, but can only be used to implement grouping-dependent slice methods

/ * * *@description: One-dimensional array to two-dimensional array (grouping) *@param {Array} Arr: * an array@param {Number} Num: Cardinality of bisection (num is grouped into groups */
const group = function (arr, num) {
    return [...Array(Math.ceil(arr.length / num)).keys()].reduce((p, _, i) = > [...p, arr.slice(i * num, (i + 1) * num)], [])
}
group([1.2.3.4.5.6.7.8.9.10].2) / / [[1, 2], [3, 4], [5, 6], [7, 8], [9.10]]
group([1.2.3.4.5.6.7.8.9.10].3) / / [[1, 2, 3], [4 and 6],,8,9 [7], [10]]
Copy the code

Implementation idea analysis:

[...Array(num).keys()]] quickly create an ascending Array
[...Array(2).keys()] / / [0, 1]
[...Array(3).keys()] / / [0, 1, 2]

Math.ceil(arr.length/num) calculates how many groups you can divide into
const arr = [1.2.3.4.5.6.7.8.9.10]
const num = 3 // Set the number of entries in the list.
Math.ceil(arr.length / num) / / 4

/ / group (,2,3,4,5,6,7,8,9,10 [1], 3) = > [[1, 2, 3], [4 and 6],,8,9 [7], [10]]
// We need to use the array slicing method slice to do the slice cutting, including the head but not the tail
// [1,2,3,4,5,6,7,8,9,10]. Slice (0,3)
// [1,2,3,4,5,6,7,8,9,10]. Slice (3,6)
// [1,2,3,4,5,6,7,8,9,10]. Slice (6,9)
/ /,2,3,4,5,6,7,8,9,10 [1]. Slice (9, 12) / / [10]

The first reduce parameter is a function, and the third parameter of the function is the index
// The second argument to reduce is optional, and the initial value of the first item p can be customized. We pass an empty array []
// I - index num - Bisector cardinalityI * num (0*3) ~ (I +1Num) * ((0+1) *3) = >0 ~ 3I * num (1*3) ~ (I +1Num) * ((1+1) *3) = >3 ~ 6I * num (2*3) ~ (I +1Num) * ((2+1) *3) = >6 ~ 9I * num (3*3) ~ (I +1Num) * ((3+1) *3) = >9 ~ 12
// We have found the index calculation rule of cutting
// Finally, the result of the process is continuously merged with the traversal, until the completion of the traversal, return the processed result
Copy the code

MDN -JavaScript reduce

Conditional grouping – groupArchive

A conditional archive for JSON arrays

/ * * *@descriptionArchive, archive one-dimensional JSON arrays (by key) *@param {Array} Arr: one-dimensional array *@param {String} Key: The key character string is */
const groupArchive = function (arr, key) {
  return [...new Set(arr.map(i= > i[key]))].reduce((p, c) = > [...p, arr.filter(i= > i[key] === c)], [])
}
let books = [
    { date: '2 months'.name: 'Chemistry Book' },
    { date: '1 month'.name: 'History book' },
    { date: '2 months'.name: 'Math book' },
    { date: 'march'.name: 'Chinese Book' },
    { date: '1 month'.name: 'Geography book' }
]
groupArchive(books, 'date')
/ * [[{date: "in February," name: "chemistry book"} {the date: "in February," name: "the math book"}], [{date: "in January," name: "history book"} {the date: "in January," name: }], [{date: "3月", name: "3月"}],] */
Copy the code

Status group – groupState

  • The JOSN array is grouped conditionally in the same order

Example:

 const list = [ 

    {name:'1'.type:0}, 
    {name:'2'.type:1}, 
    {name:'3'.type:1}, 
    {name:'4'.type:1}, 

    {name:'5'.type:0}, 
    {name:'6'.type:0}, 

    {name:'7'.type:2}, 
    {name:'8'.type:2}, 
    {name:'9'.type:2}, 

    {name:'10'.type:0},
    {name:'11'.type:0},]/* [ [{name:'1',type:0}], [{name:'2',type:1}, {name:'3',type:1}, {name:'4',type:1}], [{name:'5',type:0}, {name:'6',type:0}], [{name:'7',type:2}, {name:'8',type:2}, {name:'9',type:2}], [{name:'10',type:0},{name:'11',type:0}], ] * /
Copy the code
/ * * *@description: Arrays are grouped by identifiers (same order after grouping) *@param {Array} List: a grouped array *@param {String} TypeStr: group identifier *@return {Array}* /

const groupState = function(list,typeStr){
    const ret = [] 
    let p = 0
    let n = 0
    for(let i=1,len=list.length; i<len; i++){const pre = list[i-1]
      const cur = list[i]
      if(pre[typeStr]! ==cur[typeStr]){ n = i ret.push(list.slice(p,n)) p = i }if(i===len-1)ret.push(list.slice(p))
    }
    return ret
}


/** * Example:  * * const list = [ {name:'1',type:0}, {name:'2',type:1}, {name:'3',type:1}, {name:'4',type:1}, {name:'5',type:0}, {name:'6',type:0}, {name:'7',type:2}, {name:'8',type:2}, {name:'9',type:2}, {name:'10',type:0}, {name:'11',type:0}, ] * demand = > convert * [[{name: '1', type: 0}], [{name: '2', type: 1}, {name: '3', type: 1}, {name: '4', type: 1}], [{name: '5', type: 0}, {name:'6',type:0}], [{name:'7',type:2}, {name:'8',type:2}, {name:'9',type:2}], [{name:'10',type:0},{name:'11',type:0}], ] * * groupState(list,'type') */
Copy the code

Ascending array generation – rangeGenerater

Sometimes, when you want to quickly generate an ascending array to implement other business logic, you have a better IEDA, you don’t have to go through the for loop, there’s a better rangeGenerater

/ * * *@description: Generates an ascending array * between start and end digits, including the start and end digits@param {Number} Min: indicates the minimum *@param {Number} Max: indicates the maximum value */
const rangeGenerater = function (min, max) {
    return Array.from({ length: max - min + 1 }, (_, i) = > i + min)
}
rangeGenerater(5.10) // [5, 6, 7, 8, 9, 10]
rangeGenerater(0.10)//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Copy the code

[…Array(num).keys()] can also quickly generate 0-num ascending arrays, but it’s not flexible enough to set ranges, although you can do other things with it.

Round – round

Sometimes, when you calculate the price, the total price, you have to round the total price, right

/** * is rounded to the specified number *@param {Number} N: decimal *@param {Number} Decimals: Round to the specified number */
const round = function (n, decimals) {
    if (decimals === undefined) return n
    return Number(Math.round(n + 'e' + (decimals || 0)) + 'e-' + (decimals || 0))
}
round(0) / / 0
round(1.23456.1)/ / 1.2
round(1.23456.2)/ / 1.23
round(1.23456.3)/ / 1.235
round(1.23456.4)/ / 1.2346
round(1.23456.5)/ / 1.23456

1.0450.toFixed(2) / / "1.04"
round(1.0450.2) / / 1.05
Copy the code

Computing – calc

Numerical calculation is nothing more than addition, subtraction, multiplication and division

// This method relies on the round method above
/** * calc *@param { number } Type: 0 plus 1 minus 2 times 3 divided by *@param { String | Number } A: Calculate the number a *@param { String | Number } B: Calculate the number b *@param { Number } Digit: Number of digits reserved for the result *@return Number | String
 */
const calc = function (type, a, b, digit) {
    let r1, r2
    try {
        r1 = a.toString().split('. ') [1].length
    } catch (e) {
        r1 = 0
    }
    try {
        r2 = b.toString().split('. ') [1].length
    } catch (e) {
        r2 = 0
    }
    let maxLen = Math.pow(10.Math.max(r1, r2))
    let tyeps = [
        round((Math.round(maxLen * a) + Math.round(maxLen * b)) / maxLen, digit), / / add
        round((Math.round(maxLen * a) - Math.round(maxLen * b)) / maxLen, digit), / /
        round((Math.round(maxLen * a) * Math.round(maxLen * b)) / (maxLen * maxLen), digit), / / by
        round(Math.round(maxLen * a) / Math.round(maxLen * b), digit) / / in addition to
    ]
    let str = String(round(tyeps[type], digit || 0))
    if (digit) {
        if (str.includes('. ')) return str.split('. ') [0] + '. ' + str.split('. ') [1].padEnd(digit, 0)
        return (str + '. ').padEnd((str + '. ').length + digit, 0)}else {
        return tyeps[type]
    }
}
 
/ / subtraction -
calc(0.2.2.2) / / '0.00'
/ / + addition
calc(1.2.2.2) / / '4.00'
/ / multiply x
calc(2.2.3.2) / / '6.00'
/ / division members present
calc(3.2.3.2) / / '0.67'
Copy the code

This calculation method is actually a calculation of the auxiliary method or can really add, subtract, multiply and divide or a little chicken ribs

Addition to add

Just two numbers and two sums, right? No, no, no, not very flexible, we want to be able to add up both numbers, and we want to add up many numbers, right, you’re not greedy, you need to be, this function depends on calc

// This function depends on calc
/** ** add *@param {Number} A: Addend *@param {Number} B: Addend *@param {Number} Digit: Result reserved digit */
const add = function (a, b, digit) {
    return Array.isArray(a) ? (a.length ? a.reduce((p, c) = > add(p, c, b), 0) : 0) : calc(0, a, b, digit)
}
Example: / * * * * * 0.1 + 0.2 and rounded to 3 decimal places * add (0.1, 0.2, 3) * * / / / "0.300"
/** ** Example: In addition to the majority, the first parameter is the cumulative number, The second parameter for and rounded to the number of decimal digits * * add ([0.1, 0.2]) / / 0.3 * add ([0.1, 0.2], 3) / / '0.300' * add ([0.1, 0.2, 1, 2], 3) / / '3.300' * * /
Copy the code

Subtraction – subtract

Function as addition, this function depends on the above calculation method calc

// This function depends on calc
/** **@param {Number} A: Minus *@param {Number} B: The minuend *@param {Number} Digit: Result reserved digit */
const subtract = function (a = 0, b = 0, digit) {
    return Array.isArray(a) ? (a.length ? a.reduce((p, c) = > subtract(p, c, b)) : 0) : calc(1, a, b, digit)
}
/**
 * 示例:
 *
 * subtract(0.1,0.12)   // -0.02
 * subtract(0.1,0.12,0) // 0
 * subtract(0.1,0.12,1) // "0.0"
 * subtract(0.1,0.12,2) // "0.02"
 * subtract(0.1,0.12,3) // "-0.020"
 *
 */
Subtract/example: * * * * * ((1.1, 3)) / / 1.9 * subtract ([1.1, 3], 1) / / "1.9" * subtract ([1.1, 3], 2) / / * * / "- 1.90"
Copy the code

Multiplication – multiply

This function relies on the above calculation method calc, multiplying the majority, multiplying the two numbers, reserving the digits

/** ** two numbers *@param {*} A: Multiplier *@param {*} B: Multiplied *@param {*} Digit: Result reserved digit */
const multiply = function (a, b, digit) {
    return Array.isArray(a) ? (a.length ? a.reduce((p, c) = > multiply(p, c, b), 1) : 0) : calc(2, a, b, digit)
}
/** * Example: * * multiply by 2.42 (1.1, 2.2) / / multiply (1.13, 0.8, 0) / / 1 * multiply (1.13, 0.8, 1) / / "0.9" * multiply (1.13, 0.8, 2) / / "0.90" * multiply (1.13, 0.8, 3) / / "0.904" * multiply (1.13, 0.8, 4) * * / / / "0.9040"
Copy the code

Division – devide

This function relies on the above calculation method calc, dividing by most, dividing by two numbers, reserving the number of digits

/** ** divide two numbers by *@param {Number} A: Divisor *@param {Number} B: Dividend *@param {Number} Digit: Result reserved digit */
const devide = function (a, b, digit) {
    return Array.isArray(a) ? (a.length >= 2 ? a.reduce((p, c) = > devide(p, c, b)) : ' ') :! a || ! b ?' ' : calc(3, a, b, digit)
}
/** * Example: * * * devide () / / "" devide (1) / /" "* devide (1, 3) / / 0.3333333333333333 * devide,3,1 (1) / /" 0.3 "* devide 31 (1) / / "0.33" * * /
/*** * Example: * * * devide () / / "" devide ([]) / /" "* devide ([1, 3]) / / 0.3333333333333333 * devide (filling [1]) / / 0.1111111111111111 * Devide ([1, 9]) / / 0.1111111111111111 * devide ([1, 9], 0) / / 0 * devide ([1, 9], 1) / / "0.1" * devide ([1, 9], 2) / / "0.11" * Devide ([1,9],3) // "0.111" * */
Copy the code

After the speech

Three online code generation and running tools are recommended

Code generated online: carbon

  1. Generate nice code snippets

Online front-end development tool: Codepen

  1. Try at ordinary times
  2. Write small demos when Posting articles
  3. When asking a question, attach a reenactment of codepen

JavaScript online sandbox environment codesandBox

I am that oneHow to achieve a slider that can stretch left and rightThe demo code is right up here,You can view the complete code of slide stretching left and right codesandbox


Weekend time for the completion of this article, I hope to help you, brainstorming is my original intention, at the same time to improve their writing level, so that the article is easier to understand, if you think this article is even a little bit useful to you, please do not mean your 👍, I will continue to work hard!

If there is a mistake in the article, please leave a message to point out, if you have a better idea, welcome to leave a message, pool wisdom, common progress!

Finally we follow the movement movement, stem our line, long time sitting in front of the computer, easy to get lumbar disease!