资讯专栏INFORMATION COLUMN

ES6 生成 range 数组和 random 数组

NotFound / 3322人阅读

摘要:作者原文章创建数组除了字面量和外,还可以通过创建,为数组的长度。生成了长度为的空数组,注意,和数组中元素赋值为是有区别的中查看空数组为,而赋值为的数组为。

作者 @zwhu
原文章 @github

创建数组除了字面量和 new Array() 外,还可以通过 Array(n) 创建,n 为数组的长度。 Array(n) 生成了长度为 n 的空数组,注意,和数组中元素赋值为 undefined 是有区别的;chrome 中查看空数组为[undefined * n],而赋值为 undefined 的数组为 [undefined, undefined, ..... , undefined]

range:

let rangeArray = (start, end) => Array(end - start + 1).fill(0).map((v, i) => i + start)

rangeArray(0,10) // return [0,1,2,3,4,5,6,7,8,9,10]

由于map不能对数组中未赋值的元素进行遍历,所以可以通过 ES6 的新方法 fill 对数组进行填充,把数组中的所有数转为0(转成什么都无所谓),然后通过 map 方法将数组中所有0都转成对应的数字。

ES5 没有 fill 方法也可以通过 Array.apply(null, {length: end - start + 1}).map((v, i) => i + start) 搞定。说起来比第一种方法速度可能更快。

random:

let randomArray = (start, end) => {
  let range = rangeArray(start, end)
    , random = []
  while (range.length) {
    let i = Math.random() * range.length | 0
    random.push(range[i])
    range.splice(i, 1)
  }
  return random
}

// test
let random = randomArray(1, 50)

console.log(random.length === 50)
console.log(Math.min.apply(Math, random) === 1)
console.log(Math.max.apply(Math, random) === 50)
console.log(random.sort((a, b) => a - b).every((v, i, a) => v === a[i - 1] || 0 + 1))

具体原理就是:生成一个 range 数组,然后随机 range 数组的长度,得到下标 i,取出 range 中下标为 i 的元素放入新数组 random 中, 删除 range 数组这个元素,接着循环,直到 range 数组被删完。

最近在看「算法」,所以厚着脸皮分析下时间复杂度吧,不对的地方欢迎指出:生成一个 range 数组,2n 次循环,循环 range 数组 n 次,所以加起来就是 3n 次,所需时间为线性级别的,时间复杂度为 O(n),所以看起来还是挺快的。

作为对比,分析一种以前经常用到的方法:

let randomArray = (start, end) => {
  let o = {}
    , length = end - start + 1
    , random = []
  while (random.length < length) {
    let i = (Math.random() * length + 1) | 0
    if (o[i]) continue
    else {
      o[i] = true
      random.push(i)
    }

  }
  return random
}

// test
let random = randomArray(1, 50)

console.log(random.length === 50)
console.log(Math.min.apply(Math, random) === 1)
console.log(Math.max.apply(Math, random) === 50)
console.log(random.sort((a, b) => a - b).every((v, i, a) => v === a[i - 1] || 0 + 1))

从上面代码可以看到在最好的情况下(不会出现 random 结果重复的情况),所需的时间复杂度为 O(n),最坏的情况下(每次都重复的话...循环到无数次),这样就只能算期望了,数学不好就不瞎算了。

自己对上面的分析之后认为在输入数特别大的情况下,前一种方法会把后一种方法碾压成渣,然而实际情况是反被轰成了渣滓,原因是忽略了splice方法,splice 是对数组的元素进行移动操作,会耗费了大量时间。

let a = [], b = []
console.time("push")
for (let i = 0; i < 1e5; i++) {
  a.push(i)
}
console.timeEnd("push")  // ==> 3ms 
console.time("splice")
for (let i = 0; i < 1e5; i++) {
  b.splice(i, 1, i)
}
console.timeEnd("splice") // ==> 21ms

从上面可以看出 splice 花费的时间远远超过 push 。

写着写着就好像与标题相差了万八千里.... 不过具体写了什么就没所谓了,权当记录。

======= 2015-11-4 更新 ======

let randomArray1 = (start, end) => {
  let range = rangeArray(start, end)
    , random = []
    , N = range.length


  while (N--) {
    let i = Math.random() * (N + 1) | 0
    random.push(range[i])
    range[i] = range[N]
    //range.splice(i, 1)
  }
  return random
}

避免使用 splice 方法,算法没什么变化;速度大大提升,测试结果如下:

console.time("random1")
let random1 = randomArray1(1, 1e5)
console.timeEnd("random1")
console.time("random2")
let random2 = randomArray2(1, 1e5)
console.timeEnd("random2")

random1: 12ms
random2: 79ms

可以看到在我的电脑下,对1万条数据的处理速度提升了接近6倍。和之前的分析结果还算是相符的。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86109.html

相关文章

  • 【整理】使用Python生成数据

    摘要:含有参数布尔值,默认为表示包含终值,设定为表示不包含终值。只要计算方法一定,随机种子一定,那么产生的随机数就不会变均匀分布随机数组浮点数产生均匀分布随机数组以内的行列随机整数以内个随机浮点数内随机选择一个数 使用Python生成数据 使用python原生函数 使用range函数可创建一个整数列表 list = range(10) # 从0开始到10 : [0, 1, 2, 3, 4, ...

    Jaden 评论0 收藏0
  • 几个有趣的算法题目

    摘要:统计元素个数排序第一步用来枚举和的大小,由题目可知,数组的长度。时间复杂度为数组长度,排序的时间为,枚举时间为,枚举时间为跨度,枚举全部元素时间为,因此算法的时间上界为实际情况下,由于剪枝等操作的存在,应优于这个时间。 本文首发 http://svtter.cn 最接近的数字 题目 一个K位的数N $$ (Kleq2000,Nleq10^{20}) $$ 找出一个比N大且最接近的数,这...

    honhon 评论0 收藏0
  • 从 保龄球得分计算方法 浅析 深度学习

    摘要:最近也在学习这方面的知识给沐神疯狂打,强烈推荐他的深度学习课程,链接大家自己去搜,就不做广告了,虽然说自己连入门都算不上,但还是想实现一下自己版本的。同时,计算方法改造成版本的。 起因 周六被小伙伴拖去游泳,美名其曰:锻炼身体。其实某人就是去泡澡的,哈哈。说正题吧,游完泳在体育场里闲逛,里面很大,转着转着看到一个保龄球馆,怀着对未知事物的好奇,决定和某人去尝试一下。我和S同学一人买了一...

    wangxinarhat 评论0 收藏0
  • 流畅的python读书笔记-第二章Python 数据结构

    摘要:把具名元组以的形式返回,我们可以利用它来把元组里的信息友好地呈现出来。数组支持所有跟可变序列有关的操作,包括和。双向队列和其他形式的队列类双向队列是一个线程安全可以快速从两端添加或者删除元素的数据类型。 列表表达式 >>> symbols = $¢£¥€¤ >>> codes = [ord(symbol) for symbol in symbols] >>> codes [36, 16...

    syoya 评论0 收藏0
  • 30s js代码片段 翻译

    摘要:可否被整除使用模运算符来检查余数是否等于。数值增加序号后缀使用模运算符来查找单位数和十位数的值。 这是对 github 上30s代码片段的翻译整理,由于作者的文档是通过脚本生成的,也就懒得去提pull了,整理了放到博客上供大家学习参考,后续会持续跟进翻译。 Array Array concatenation (合并参数) 使用 Array.concat() 来连接参数中的任何数组或值。...

    sevi_stuo 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<