There are some JavaScript array methods that I don’t know if you’ve ever teased
- Why only forward lookup
find
,findIndex
And 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 correctly
delByIndexs
methods - 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, because
findIndex
You 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
- Generate nice code snippets
Online front-end development tool: Codepen
- Try at ordinary times
- Write small demos when Posting articles
- 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!