js for循环 性能大比拼[超高散分]

cn00439805 2020-09-27 05:19:41
需求:
从一个30万数据量的一个一维数组中,以20个点为间隔,取20个点中的最大值,最小值,中值,并按原数组中的顺序生成新的3个点(也就是20个点变成3个点);由于以20个点取中值,中间2个值任取1个即可,如果最大值,最小值,中值有相同的,任取一个即可,但要保证取完的3值在原20个点中的前后顺序一致;最后生成一个4万5千数据良的新数组。
当前代码耗时大约是550ms之间,希望能优化性能,减少js执行时间;代码耗时越少,我给的分越高,谢谢大家帮忙。

以20个点为例子:
[5,67,34,2,56,123,66,77,88,8,22,187,1,99,88,77,34,2,1,99] 应该得到 [66,187,1] 或者 [56,187,1] 都可以

当前待优化代码:

const generateRandomData = (total = 4000, max = 200, min = 10) => { //随机生成长度为total的数组,数组中每个数字为min到max之间
const arr = []
for (let i = 0; i < total; i++) {
arr[i] = min + ~~(Math.random() * (max - min + 1))
}
return arr
}

const getThreeValDataByCompleteData = (data, step = 20) => { //获取满足需求的点的数组
let resArr = []
for (let i = 0; i < data.length; i += step) {
let arr = data.slice(i, i + step),
arrlen = arr.length,
sortArr = arr.concat().sort((a, b) => a - b),
max = sortArr[arrlen - 1],
min = sortArr[0],
center = sortArr[Math.ceil(arrlen / 2)]
let num = 3, n = 0, threeValArr = Array(num)
let maxExist = true, minExist = true, centerExist = true
for (let j = 0; j < arrlen; j++) {
if (arr[j] === max && maxExist) {
maxExist = false
threeValArr[n++] = arr[j]
}
else if (arr[j] === min && minExist) {
minExist = false
threeValArr[n++] = arr[j]
}
else if (arr[j] === center && centerExist) {
centerExist = false
threeValArr[n++] = arr[j]
}
if (n === num) break;
}
resArr = resArr.concat(threeValArr)
}
return resArr
}

let interval = 20 //每多少个点生成间隔数组
let data = generateRandomData(300000,interval) //随机生成长度为30万的数组,数组中每个数字为10到200之间
console.time()
let res = getThreeValDataByCompleteData(data) //通过函数获取4.5万满足需求的点
console.timeEnd()
console.log(`随机生成${data.length}个点,以${interval}个点作为间隔数组,每个间隔数组按顺序得到最小值,最大值,平均值这三个点(顺序按照3个值实际在数组中的顺序),最后生成${res.length}个点,共耗时上述毫秒值。`)


...全文
4707 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_50944805 2020-09-29
  • 打赏
  • 举报
回复
再次优化,减少一个for循环

const generateRandomData = (total = 4000, max = 200, min = 10) => { //随机生成长度为total的数组,数组中每个数字为min到max之间
				const arr = []
				console.time('generateRandomData')
				let i = 0
				while(total > i){
					arr[i++] = (min + ~~(Math.random() * (max - min + 1)))
				}
				console.timeEnd('generateRandomData')
				return arr
			}


const getThreeValDataByCompleteData = (data, step = 20) => {
				
				// const stepData = []
				const myarr = []
				let arr = []
				for(let i = 0; i < data.length; i += step){
					// stepData.push(data.slice(i, i + step))
					arr = data.slice(i, i + step)
					const max = Math.max(...arr),
					 min = Math.min(...arr),
					 age = (max - min) / 2 + min,
					 complete = []
					let diff = age
					 middle = diff,
					 index = 0,
					 count = 0
					for(let k = 0; k < arr.length; k++){
						count = Math.abs(arr[k] - age)
						if(max == arr[k]){
							complete[k] = max
						}else if(min == arr[k]){
							complete[k] = min
						}else	if(diff > count){
							diff = count
							middle = arr[k]
							index = k
						}
					}
					complete[index] = middle
					myarr.push(...Array.from(new Set(complete)).filter(item => item != undefined))
				}
				
				return myarr
			}

let interval = 20  //每多少个点生成间隔数组
			let data = generateRandomData(300000,interval)   //随机生成长度为30万的数组,数组中每个数字为10到200之间
			console.time('time')
			let res = getThreeValDataByCompleteData(data, interval)    //通过函数获取4.5万满足需求的点
			console.timeEnd('time')
			console.log(`随机生成${data.length}个点,以${interval}个点作为间隔数组,每个间隔数组按顺序得到最小值,最大值,平均值这三个点(顺序按照3个值实际在数组中的顺序),最后生成${res.length}个点,共耗时上述毫秒值。`)
			

weixin_50944805 2020-09-29
  • 打赏
  • 举报
回复
我上面的 帖子修改不了,我重发一边新的。 我上一个的算法有问题,算中间值的时候应该时:(最大值 - 最小值 )/ 2 + 最小值 才对,上一次忘记最后加上最小值了 下面是修复Bug版本,时间是 22ms -- 28ms

const generateRandomData = (total = 4000, max = 200, min = 10) => { //随机生成长度为total的数组,数组中每个数字为min到max之间
				const arr = []
				let i = 0
				while(total > i){
					arr[i++] = (min + ~~(Math.random() * (max - min + 1)))
				}
				return arr
			}

const getThreeValDataByCompleteData = (data, step = 20) => {
				
				const stepData = []
				const myarr = []
				for(let i = 0; i < data.length; i += step){
					stepData.push(data.slice(i, i + step))
				}
				stepData.map(v => {
					const max = Math.max(...v)
					const min = Math.min(...v)
					const age = (max - min) / 2 + min
					let diff = age
					let middle = diff
					let index = 0
					const complete = []
					for(let k = 0; k < v.length; k++){
						const count = Math.abs(v[k] - age)
						if(max == v[k]){
							complete[k] = max
						}else if(min == v[k]){
							complete[k] = min
						}else	if(diff > count){
							diff = count
							middle = v[k]
							index = k
						}
					}
					complete[index] = middle
					// const arr = Array.from(new Set(complete)).filter(item => item != undefined)
					myarr.push(...Array.from(new Set(complete)).filter(item => item != undefined))
					// if(arr.length < 3){
					// 	console.log(v, arr, max, min, age)
					// }
					
					// return complete
				})
				
				return myarr
			}

let interval = 20  //每多少个点生成间隔数组
			let data = generateRandomData(300000,interval)   //随机生成长度为30万的数组,数组中每个数字为10到200之间
			console.time('time')
			let res = getThreeValDataByCompleteData(data, interval)    //通过函数获取4.5万满足需求的点
			console.timeEnd('time')
			console.log(`随机生成${data.length}个点,以${interval}个点作为间隔数组,每个间隔数组按顺序得到最小值,最大值,平均值这三个点(顺序按照3个值实际在数组中的顺序),最后生成${res.length}个点,共耗时上述毫秒值。`)


qybao 2020-09-29
  • 打赏
  • 举报
回复
也来凑个热闹,测试基本再50ms左右
const generateRandomData = (total = 4000, max = 200, min = 10) => { //随机生成长度为total的数组,数组中每个数字为min到max之间
const arr = []
for (let i = 0; i < total; i++) {
arr[i] = min + ~~(Math.random() * (max - min + 1))
}
return arr
};

const getThreeValDataByCompleteData = (data, step = 20) => { //获取满足需求的点的数组
let resArr = []
for (let i = 0; i < data.length; i += step) {
let arr = []
data.slice(i, i + step).forEach((val, idx)=>{
arr.push({val: val, idx: idx}) //用对象直接记住位置(索引)和值信息
})
let arrlen = arr.length
//以值排序,过滤(最小,最大,中值),再以位置(索引)排序,最后去掉索引信息只保留值信息
arr.sort((a,b)=>a.val-b.val)
.filter((val, idx)=>(idx==0||idx==arrlen-1||idx==Math.ceil(arrlen / 2)))
.sort((a,b)=>a.idx-b.idx)
.forEach(e=>{
resArr.push(e.val)
})
}
return resArr
}

//验证样例数据
//let testData = [5,67,34,2,56,123,66,77,88,8,22,187,1,99,88,77,34,2,1,99]
//let testRes = getThreeValDataByCompleteData(testData)
//console.log(testRes)

let interval = 20 //每多少个点生成间隔数组
let data = generateRandomData(300000,interval) //随机生成长度为30万的数组,数组中每个数字为10到200之间
console.time('time')
let res = getThreeValDataByCompleteData(data) //通过函数获取4.5万满足需求的点
console.timeEnd('time')
console.log(`随机生成${data.length}个点,以${interval}个点作为间隔数组,每个间隔数组按顺序得到最小值,最大值,平均值这三个点(顺序按照3个值实际在数组中的顺序),最后生成${res.length}个点,共耗时上述毫秒值。`)

weixin_50944805 2020-09-28
  • 打赏
  • 举报
回复

function generateRandomData(){
                                const arr = []
				console.time('generateRandomData')
				let i = 0
                                // 用while循环还能快一点点,可能有时候快个1~2 ms,有时候没区别,感知不强
				while(total > i){
					arr[i++] = (min + ~~(Math.random() * (max - min + 1)))
				}
				// for (let i = 0; i < total; i++) {
				// 	arr[i] = (min + ~~(Math.random() * (max - min + 1)))
				// }
				console.timeEnd('generateRandomData')
				return arr
}
weixin_50944805 2020-09-28
  • 打赏
  • 举报
回复
打回重做了一下,刚开始没有考虑到有重复的相同的数据 我测试的时间时:my: 23.765869140625 ms 具体有没有符合你的需求,和对不对,还是有BUG,这我没有仔细测试过

const generateRandomData = (total = 4000, max = 200, min = 10) => { //随机生成长度为total的数组,数组中每个数字为min到max之间
				const arr = []
				console.time('generateRandomData')
				for (let i = 0; i < total; i++) {
					arr[i] = (min + ~~(Math.random() * (max - min + 1)))
				}
				console.timeEnd('generateRandomData')
				return arr
			}

			// const getThreeValDataByCompleteData = (data, step = 20) => { //获取满足需求的点的数组
			// 	console.time('getThreeValDataByCompleteData')
			// 	let resArr = []
			// 	for (let i = 0; i < data.length; i += step) {
			// 		let arr = data.slice(i, i + step),
			// 			arrlen = arr.length,
			// 			sortArr = arr.concat().sort((a, b) => a - b),
			// 			max = sortArr[arrlen - 1],
			// 			min = sortArr[0],
			// 			center = sortArr[Math.ceil(arrlen / 2)]
			// 		let num = 3,
			// 			n = 0,
			// 			threeValArr = Array(num)
			// 		let maxExist = true,
			// 			minExist = true,
			// 			centerExist = true
			// 		for (let j = 0; j < arrlen; j++) {
			// 			if (arr[j] === max && maxExist) {
			// 				maxExist = false
			// 				threeValArr[n++] = arr[j]
			// 			} else if (arr[j] === min && minExist) {
			// 				minExist = false
			// 				threeValArr[n++] = arr[j]
			// 			} else if (arr[j] === center && centerExist) {
			// 				centerExist = false
			// 				threeValArr[n++] = arr[j]
			// 			}
			// 			if (n === num) break;
			// 		}
			// 		resArr = resArr.concat(threeValArr)
			// 	}
			// 	console.timeEnd('getThreeValDataByCompleteData')
			// 	return resArr
			// }
			
			function getThreeValDataByCompleteData(data, step = 20){
				
				const stepData = []
				for(let i = 0; i < data.length; i += 20){
					stepData.push(data.slice(i, i + step))
				}
				console.log(data.length)
				const operation = stepData.map(v => {
					const max = Math.max(...v)
					const min = Math.min(...v)
					const age = (max - min) / 2
					let diff = (max - min) / 2
					let middle = diff
					let index = 0
					const complete = []
					for(let k = 0; k < v.length; k++){
						const count = Math.abs(v[k] - age)
						if(max == v[k]){
							complete[k] = max
						}else if(min == v[k]){
							complete[k] = min
						}else	if(diff > count){
							diff = count
							middle = v[k]
							index = k
						}
					}
					complete[index] = middle
					return Array.from(new Set(complete)).filter(item => item != undefined)
				})
				
				return operation
			}


			let interval = 20 //每多少个点生成间隔数组
			let data = generateRandomData(300000) //随机生成长度为30万的数组,数组中每个数字为10到200之间
			// console.time()
			// let res = getThreeValDataByCompleteData(data, interval) //通过函数获取4.5万满足需求的点
			// console.timeEnd()
			// console.log(
			// 	`随机生成${data.length}个点,以${interval}个点作为间隔数组,每个间隔数组按顺序得到最小值,最大值,平均值这三个点(顺序按照3个值实际在数组中的顺序),最后生成${res.length}个点,共耗时上述毫秒值。`
			// )
			console.time('my')
			const my = getThreeValDataByCompleteData(data, interval)
			console.timeEnd('my')
			console.log(my)
風灬雲 2020-09-28
  • 打赏
  • 举报
回复

      const generateRandomData = (total = 4000, max = 200, min = 10) => { //随机生成长度为total的数组,数组中每个数字为min到max之间
         const arr = []
         for (let i = 0; i < total; i++) {
            arr[i] = min + ~~(Math.random() * (max - min + 1))
         }
         return arr
      }
 
      const getThreeValDataByCompleteData = (data, step = 20) => { //获取满足需求的点的数组
         let resArr = []
         for (let i = 0; i < data.length; i += step) {
            let arr = data.slice(i, i + step),
               arrlen = arr.length,
               sortArr = arr.concat().sort((a, b) => a - b),
               max = sortArr[arrlen - 1],
               min = sortArr[0],
               center = sortArr[Math.ceil(arrlen / 2)]
            let indexArr = [arr.indexOf(max),arr.indexOf(min),arr.indexOf(center)];
             indexArr.sort();
                indexArr.forEach(e => {
                resArr.push(arr[e])
            })
         }
         return resArr
      }
 
      let interval = 20  //每多少个点生成间隔数组
      let data = generateRandomData(300000,interval)   //随机生成长度为30万的数组,数组中每个数字为10到200之间
      console.time()
      let res = getThreeValDataByCompleteData(data)    //通过函数获取4.5万满足需求的点
      console.timeEnd()
      console.log(`随机生成${data.length}个点,以${interval}个点作为间隔数组,每个间隔数组按顺序得到最小值,最大值,平均值这三个点(顺序按照3个值实际在数组中的顺序),最后生成${res.length}个点,共耗时上述毫秒值。`)

测试 都在40-70ms之间
cn00439805 2020-09-27
  • 打赏
  • 举报
回复
有一行参数interval传错了,以下面的代码为准

      let interval = 20  //每多少个点生成间隔数组
      let data = generateRandomData(300000)   //随机生成长度为30万的数组,数组中每个数字为10到200之间
      console.time()
      let res = getThreeValDataByCompleteData(data,interval)    //通过函数获取4.5万满足需求的点
      console.timeEnd()
      console.log(`随机生成${data.length}个点,以${interval}个点作为间隔数组,每个间隔数组按顺序得到最小值,最大值,平均值这三个点(顺序按照3个值实际在数组中的顺序),最后生成${res.length}个点,共耗时上述毫秒值。`)

87,917

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧