100万条数据查找指定元素性能对比
“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第2篇文章,点击查看活动详情”
首先提出问题:
[1,2,3,4...].includes(2) 比执行for循环更快吗?Array.indexOf更好吗 ?
数组中查找某个元素应该是我们在实际开发中遇到高频问题,那么大家有想过includes,for循环,Arry.indexOf等查找方法究竟那个查找的更快吗?本文将通过真实数据去和大家一步步探讨。
带着上面的疑问,一起来看下结果,本文测试了以下常用方法:
- includes
- indexOf
- findIndex
- some
- find
- existsInArrayFor
第一步,
我们需要造一百万条数据, 有同学说那还不简单,直接for循环100万次不就解决了嘛,
var arr = []
for (var i = 0; i < 1000000; i++) {
arr.push(i)
}
执行了上面的代码我们果真得到了100万长度的数组,但是这不是我们想要的,我们想要的是包含 100 万个字符串的 JSON 数组,每个字符串需要有 500 个随机生成的字符 (这样数据更真实一点) 那有同学说:那再循环1000000次每次生成随机的500个字符串不就行了,试了一下,等了10秒钟之后,浏览器崩了,哈哈~
function randomString(length = 10) {
var result = ''
var characters =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
var charactersLength = characters.length
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength))
}
return result
}
var arr = []
for (var i = 0; i < 1000000; i++) {
arr.push(randomString(500))
}
这可咋办啊,这样的大数据直接去js生成肯定不行,我们可以通过node去生成一个包含100万条数据的json文件就可以了,代码如下:
// 生成大数据json文件
const fs = require('fs')
function generateRandomString (length = 10) {
var result = ''
var characters =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
var charactersLength = characters.length
for (var i = 0;i < length;i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength))
}
return result
}
function generateFileArray (filePath, length, generator) {
function writeOpenArray (filePath) {
fs.writeFileSync(filePath, 'var generatorData = [', {flag: 'a+'})
}
function writeCloseArray (filePath) {
fs.writeFileSync(filePath, ']', {flag: 'a+'})
}
function writeArrayEntry (filePath, arr) {
const stringifiedArray = JSON.stringify(arr)
let arrayWithoutBrackets = stringifiedArray.slice(1, stringifiedArray.length - 1)
fs.writeFileSync(filePath, `${arrayWithoutBrackets},`, {flag: 'a+'})
}
writeOpenArray(filePath)
for (let i = 0;i < length;i++) {
writeArrayEntry(filePath, [generator()])
console.log(`Progress: ${((i * 100) / length).toFixed(2)}%`)
}
writeCloseArray(filePath)
}
function start () {
const OUTPUT_FILE = './data.json'
// 生成100万条长度随机字符串
generateFileArray(OUTPUT_FILE, 1000000, () => {
return generateRandomString(500)
})
}
start()
通过node执行这个js就能生成100万条数据的json文件了
第二步,
我们拿到了一百万条数据之后就要对上面几种方法进行测试了,写一个html去进行测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>测试</title>
</head>
<body>
</body>
<script src="./data.json"></script>
<script>
function includes (arr, elem) {
return arr.includes(elem)
}
function indexOf (arr, elem) {
return arr.indexOf(elem) > -1
}
function findIndex (arr, elem) {
return arr.findIndex((value) => elem === value) > -1
}
function some (arr, elem) {
return arr.some((value) => elem === value) > -1
}
function find (arr, elem) {
return arr.find((e) => e === elem) != null
}
function existsInArrayFor (arr, targetElem) {
for (let i = 0;i < arr.length;i++) {
if (arr[i] === targetElem) return true
}
return false
}
// 为了保持元素位置,取数组中间位置的值进行查找
function testFunc (funcName, inputArray) {
const elementToFind = inputArray[inputArray.length / 2]
const start = performance.now()
const result = funcName(inputArray, elementToFind)
const end = performance.now()
console.log(end - start)
return end - start
}
</script>
</html>
用Google浏览器对不同方法各自测试了30次之后,去掉最高值和最低值,得到每个方法的消耗的平均时间,结果如下:
- includes
- indexOf
- findIndex
- some
- find
- existsInArrayFor
方法 | 平均耗时(ms) |
---|---|
includes |
11.51 |
indexOf |
11.94 |
existsInArrayFor |
13.98 |
some |
18.26 |
findIndex |
19.75 |
find |
21.62 |
通过以上的数组可以得到以下两点结论:
find
,some
和findIndex
貌似比其他几个慢了不少- 在处理大数据字符串时,
includes
和indexOf
比其他的方法快了不少
当然上面只是对一组数据进行了测试,可能在不同的模拟数据和机器下表现出来的结果有不同的结果,感兴趣的可以自己试试~
转载自:https://juejin.cn/post/7141288736632864798