要从debian10升级到debian12,需要执行两次升级脚本才行。
Debian 9 升级到 Debian 10
Debian 10 升级到 Debian 11
Debian 11 升级到 Debian 12

内核升级到了6.10
没有 ifupdown 了, 默认网络管理程序更换为 systemd-networkd

开始升级

先看看自己是那个debian的版本
cat /etc/debian_version
或者
cat /etc/os-release
然后就一键脚本了

bash <(curl -sSL https://raw.githubusercontent.com/wikihost-opensource/linux-toolkit/main/system-upgrade/debian.sh)

脚本作者链接地址


人生值得关注的事情少之又少,我们就才区区三万多天。
说心里话,人生值得在乎的人不就那么几个人嘛…

你的亲人,三五个知己。这是每天跟你交流的一些人,他们才是你最应该在乎的。

那些你都没有见过面的人,或者以后一辈子都不会再见的人,无论是批评也罢,赞赏也罢,那可能并不是那么的重要,你最要在乎的其实还是你身边的人,你所爱的人…他们的意见,所以从这个角度而言,我们又要在乎一些事情又不要在乎一些事情。

因为人最终还是要认识到你自己。

人性就是不喜欢被别人批评,喜欢被别人夸奖,但是你要会发现,你有多么的在乎别人的夸奖,那么你也就有多么厌恶别人的批评。
你有多么宽容别人的批评,你就有多么这个对于他人的赞扬,保持一种从容。这是一种理性的一种态度

孔老夫子说,君子求诸己小人求诸人。就是你始终要去思考你有哪些做得确实不合适的一些地方,
所以从这个角度来讲,我现在觉得还是善意的对待一些不想听的声音,因为他会让你变得坚强,他会让你走出自恋。

真正的幸福并不是得到你极力追求的东西,而是那些习以为常的,直到失去才后悔莫及的东西。

说实话,人生真的不容易,所以只有经历了黑暗,你才能感恩生活中一切的习以为常,一切平凡的幸福,你才会觉得那些真的就是极大的幸福。

时间看似属于我们,又不属于我们,我们只是时间的代理人。
只能把握好我们暂时管理的时间,人生的每一刻都是一个记忆的碎片,镶嵌在我们脑海的深处,不经意间就会在我们心中激起涟漪,让我们回忆起那些曾经拥有的幸福


Markdown数学公式语法

行内与独行

  1. 行内公式:将公式插入到本行内,符号:$公式内容$,如:$xyz$
  2. 独行公式:将公式插入到新的一行内,并且居中,符号:$$公式内容$$,如:$$xyz$$

上标、下标与组合

  1. 上标符号,符号:^,如:$x^4$
  2. 下标符号,符号:_,如:$x\_1$
  3. 组合符号,符号:{},如:${16}\_{8}O{2+}\_{2}$

汉字、字体与格式

  1. 汉字形式,符号:\mbox{},如:$V\_{\\mbox{初始}}$
  2. 字体控制,符号:\displaystyle,如:$\\displaystyle \\frac{x+y}{y+z}$
  3. 下划线符号,符号:\underline,如:$\\underline{x+y}$
  4. 标签,符号\tag{数字},如:$\\tag{11}$
  5. 上大括号,符号:\overbrace{算式},如:$\\overbrace{a+b+c+d}^{2.0}$
  6. 下大括号,符号:\underbrace{算式},如:$a+\\underbrace{b+c}\_{1.0}+d$
  7. 上位符号,符号:\stacrel{上位符号}{基位符号},如:$\\vec{x}\\stackrel{\\mathrm{def}}{=}{x\_1,\\dots,x\_n}$

占位符

  1. 两个quad空格,符号:\qquad,如:$x \\qquad y$
  2. quad空格,符号:\quad,如:$x \\quad y$
  3. 大空格,符号\,如:$x \\ y$
  4. 中空格,符号\:,如:$x : y$
  5. 小空格,符号\,,如:$x , y$
  6. 没有空格,符号\`\`,如:$xy$
  7. 紧贴,符号\!,如:$x ! y$

定界符与组合

  1. 括号,符号:()\big(\big) \Big(\Big) \bigg(\bigg) \Bigg(\Bigg),如:$()\\big(\\big) \\Big(\\Big) \\bigg(\\bigg) \\Bigg(\\Bigg)$
  2. 中括号,符号:[],如:$\[x+y\]$
  3. 大括号,符号:\{ \},如:${x+y}$
  4. 自适应括号,符号:\left \right,如:$\\left(x\\right)$,$\\left(x{yz}\\right)$
  5. 组合公式,符号:{上位公式 \choose 下位公式},如:${n+1 \\choose k}={n \\choose k}+{n \\choose k-1}$
  6. 组合公式,符号:{上位公式 \atop 下位公式},如:$\\sum\_{k\_0,k\_1,\\ldots>0 \\atop k\_0+k\_1+\\cdots=n}A\_{k\_0}A\_{k\_1}\\cdots$

四则运算

  1. 加法运算,符号:+,如:$x+y=z$
  2. 减法运算,符号:-,如:$x-y=z$
  3. 加减运算,符号:\pm,如:$x \\pm y=z$
  4. 减甲运算,符号:\mp,如:$x \\mp y=z$
  5. 乘法运算,符号:\times,如:$x \\times y=z$
  6. 点乘运算,符号:\cdot,如:$x \\cdot y=z$
  7. 星乘运算,符号:\ast,如:$x \\ast y=z$
  8. 除法运算,符号:\div,如:$x \\div y=z$
  9. 斜法运算,符号:/,如:$x/y=z$
  10. 分式表示,符号:\frac{分子}{分母},如:$\\frac{x+y}{y+z}$
  11. 分式表示,符号:{分子} \voer {分母},如:${x+y} \\over {y+z}$
  12. 绝对值表示,符号:||,如:$|x+y|$

高级运算

  1. 平均数运算,符号:\overline{算式},如:$\\overline{xyz}$
  2. 开二次方运算,符号:\sqrt,如:$\\sqrt x$
  3. 开方运算,符号:\sqrt[开方数]{被开方数},如:$\\sqrt\[3\]{x+y}$
  4. 对数运算,符号:\log,如:$\\log(x)$
  5. 极限运算,符号:\lim,如:$\\lim^{x \\to \\infty}\_{y \\to 0}{\\frac{x}{y}}$
  6. 极限运算,符号:\displaystyle \lim,如:$\\displaystyle \\lim^{x \\to \\infty}\_{y \\to 0}{\\frac{x}{y}}$
  7. 求和运算,符号:\sum,如:$\\sum^{x \\to \\infty}\_{y \\to 0}{\\frac{x}{y}}$
  8. 求和运算,符号:\displaystyle \sum,如:$\\displaystyle \\sum^{x \\to \\infty}\_{y \\to 0}{\\frac{x}{y}}$
  9. 积分运算,符号:\int,如:$\\int^{\\infty}\_{0}{xdx}$
  10. 积分运算,符号:\displaystyle \int,如:$\\displaystyle \\int^{\\infty}\_{0}{xdx}$
  11. 微分运算,符号:\partial,如:$\\frac{\\partial x}{\\partial y}$
  12. 矩阵表示,符号:\begin{matrix} \end{matrix},如:$\\left\[ \\begin{matrix} 1 &2 &\\cdots &4\\5 &6 &\\cdots &8\\\\vdots &\\vdots &\\ddots &\\vdots\\13 &14 &\\cdots &16\\end{matrix} \\right\]$

逻辑运算

  1. 等于运算,符号:=,如:$x+y=z$
  2. 大于运算,符号:>,如:$x+y>z$
  3. 小于运算,符号:<,如:$x+y<z$
  4. 大于等于运算,符号:\geq,如:$x+y \\geq z$
  5. 小于等于运算,符号:\leq,如:$x+y \\leq z$
  6. 不等于运算,符号:\neq,如:$x+y \\neq z$
  7. 不大于等于运算,符号:\ngeq,如:$x+y \\ngeq z$
  8. 不大于等于运算,符号:\not\geq,如:$x+y \\not\\geq z$
  9. 不小于等于运算,符号:\nleq,如:$x+y \\nleq z$
  10. 不小于等于运算,符号:\not\leq,如:$x+y \\not\\leq z$
  11. 约等于运算,符号:\approx,如:$x+y \\approx z$
  12. 恒定等于运算,符号:\equiv,如:$x+y \\equiv z$

集合运算

  1. 属于运算,符号:\in,如:$x \\in y$
  2. 不属于运算,符号:\notin,如:$x \\notin y$
  3. 不属于运算,符号:\not\in,如:$x \\not\\in y$
  4. 子集运算,符号:\subset,如:$x \\subset y$
  5. 子集运算,符号:\supset,如:$x \\supset y$
  6. 真子集运算,符号:\subseteq,如:$x \\subseteq y$
  7. 非真子集运算,符号:\subsetneq,如:$x \\subsetneq y$
  8. 真子集运算,符号:\supseteq,如:$x \\supseteq y$
  9. 非真子集运算,符号:\supsetneq,如:$x \\supsetneq y$
  10. 非子集运算,符号:\not\subset,如:$x \\not\\subset y$
  11. 非子集运算,符号:\not\supset,如:$x \\not\\supset y$
  12. 并集运算,符号:\cup,如:$x \\cup y$
  13. 交集运算,符号:\cap,如:$x \\cap y$
  14. 差集运算,符号:\setminus,如:$x \\setminus y$
  15. 同或运算,符号:\bigodot,如:$x \\bigodot y$
  16. 同与运算,符号:\bigotimes,如:$x \\bigotimes y$
  17. 实数集合,符号:\mathbb{R},如:\mathbb{R}
  18. 自然数集合,符号:\mathbb{Z},如:\mathbb{Z}
  19. 空集,符号:\emptyset,如:$\\emptyset$

数学符号

  1. 无穷,符号:\infty,如:$\\infty$
  2. 虚数,符号:\imath,如:$\\imath$
  3. 虚数,符号:\jmath,如:$\\jmath$
  4. 数学符号,符号\hat{a},如:$\\hat{a}$
  5. 数学符号,符号\check{a},如:$\\check{a}$
  6. 数学符号,符号\breve{a},如:$\\breve{a}$
  7. 数学符号,符号\tilde{a},如:$\\tilde{a}$
  8. 数学符号,符号\bar{a},如:$\\bar{a}$
  9. 矢量符号,符号\vec{a},如:$\\vec{a}$
  10. 数学符号,符号\acute{a},如:$\\acute{a}$
  11. 数学符号,符号\grave{a},如:$\\grave{a}$
  12. 数学符号,符号\mathring{a},如:$\\mathring{a}$
  13. 一阶导数符号,符号\dot{a},如:$\\dot{a}$
  14. 二阶导数符号,符号\ddot{a},如:$\\ddot{a}$
  15. 上箭头,符号:\uparrow,如:$\\uparrow$
  16. 上箭头,符号:\Uparrow,如:$\\Uparrow$
  17. 下箭头,符号:\downarrow,如:$\\downarrow$
  18. 下箭头,符号:\Downarrow,如:$\\Downarrow$
  19. 左箭头,符号:\leftarrow,如:$\\leftarrow$
  20. 左箭头,符号:\Leftarrow,如:$\\Leftarrow$
  21. 右箭头,符号:\rightarrow,如:$\\rightarrow$
  22. 右箭头,符号:\Rightarrow,如:$\\Rightarrow$
  23. 底端对齐的省略号,符号:\ldots,如:$1,2,\\ldots,n$
  24. 中线对齐的省略号,符号:\cdots,如:$x\_1^2 + x\_2^2 + \\cdots + x\_n^2$
  25. 竖直对齐的省略号,符号:\vdots,如:$\\vdots$
  26. 斜对齐的省略号,符号:\ddots,如:$\\ddots$

希腊字母

字母实现字母实现
AAα\alhpa
BBβ\beta
Γ\Gammaγ\gamma
Δ\Deltaδ\delta
EEϵ\epsilon
ZZζ\zeta
HHη\eta
Θ\Thetaθ\theta
IIι\iota
KKκ\kappa
Λ\Lambdaλ\lambda
MMμ\mu
NNν\nu
Ξ\Xiξ\xi
OOο\omicron
Π\Piπ\pi
PPρ\rho
Σ\Sigmaσ\sigma
TTτ\tau
Υ\Upsilonυ\upsilon
Φ\Phiϕ\phi
XXχ\chi
Ψ\Psiψ\psi
Ω\vω\omega


JavaScript 数组高性能去重 千万级数据去重效率测试 高效去重详解

引言

  网上能搜出一堆关于数据去重的例子,以及测试效率耗时都不尽相同。然而却没给出必要的解释,为什么不同人测试出来的效率不一样呢?本文就详细通过大量测试探索一下,去重效率损耗主要在哪儿?不一样的数据为什么用不同去重方案测试效率耗时不一样?给千万级的数据去重该选用哪种去重方法?

测试前提

1.测试工具 chrome浏览器
2.测试电脑配置 小米笔记本 i7-8500U 16GB
3.系统 windows10 64位

测试准备

  分别创建一个1万、10万、100万、1000万的简单数据,这里我们不取随机数,创建固定重复的量的数据(分别重复20%,50%,80%)。并使重复数据平均分布,测试各种常用去重方法效率。

// distinctTest.js
var myriad = [];
// 代码就写一个1万的例子,避免篇幅过长。
[2, 5, 8].map(item => {
  myriad.push(Array.from(new Array(10000), function (item2, i) {
    return i % 10 < item || Math.random();
  }))
  // 可在此处添加十万、百万.. 数据
})

function distinct(arr) {
    // 此处为去重代码
  return arr;
}

myriad.forEach(item => {
  var length = item.length;
  console.log(`数据长度:${item.length}`)
  console.time("耗时")
  var newArr = distinct(item)
  console.timeEnd("耗时")
  console.log(`数据重复量:${length - newArr.length}`)
  console.log('————————————————————————————————————————————')
})
123456789101112131415161718192021222324

测试效率

1.双重for循环 + splice / flag

方法解释:
  第一种在元素重复时删除重复的元素,剩余的元素就是去重后的数据。splice会改变原数组,如果不想更改,可以用concat复制一份,如:var newArr = arr.concat()不传入数据相当于复刻一份。
  第二种就是用flag标记,新数组中存在相同数据就不往新数组插入当前数据。
去重代码:

// 使用splice删除
function distinct(arr) {
  for (var i = 0, len = arr.length; i < len; i++) {
    for (var i2 = i + 1; i2 < len; i2++) {
      if (arr[i] === arr[i2]) { 
        arr.splice(i2, 1); // 删除重复的数据
        i2--; // 删除数据后index需要前移一位
        len = arr.length; // 删除数据后重新获取数组长度
      }
    }
  }
  return arr;
}

// 使用flag标记
function distinct(arr) {
  var newArr = []
  for (var i = 0, len = arr.length; i < len; i++) {
    var flag = true
    for (var i2 = 0; i2 < newArr.length; i2++) {
      if (arr[i] === newArr[i2]) { 
        flag = false
        break;
      }
    }
    flag && newArr.push(arr[i])
  }
  return newArr;
}

123456789101112131415161718192021222324252627282930

测试结果:
splice
测试结果图
flag

`数据长度:10000`             | `数据长度:100000`             | `数据长度:1000000`
数据重复量:1999              | 数据重复量:19999             | 页面崩溃
耗时: 98.783935546875ms         | 耗时: 9475.10009765625ms     | 
——————————————————————————     | ——————————————————————————     |
数据重复量:4999              | 数据重复量:49999             |
耗时: 46.31298828125ms         | 耗时: 3659.33984375ms        | 
——————————————————————————     | ——————————————-———————————    | 
数据重复量:7999              | 数据重复量:79999             | 
耗时: 7.68310546875ms         | 耗时: 587.00927734375ms        | 
123456789

结果描述:
  双重循环去重,使用splice,会更改原来数组数据,在数据不到1万时,处理效率还可接受。达到10万时需要10多秒,达到100万页面直接崩溃。使用flag判断稍快于上方,而且重复数据越多,耗时差异越大。

方法效率分析:
  1.splice删除数据元素,100万条数据都删除,耗时在8秒(8000ms)左右,波动幅度较大,根据重复量多少,效率损耗有明显差异。
  2. 1万条平均分布的数据,重复20%,需要循环3千多万次,重复50%,需要循环1千多万次,重复80%,需要循环2百多万次。而十万条数据在此之上翻了100倍,从以上1万数据与10万数据耗时也能看出,时长比超过100倍。因循环次数的急剧增多,耗时也100倍增长。

2.for 循环加 indexOf / includes

方法解释:
  此方法通过判断新数组中是否存在当前循环到的元素,如果没有就把当前循环到的元素插入新数组。

去重代码:

function distinct(arr) {
  var newArray = [];
  for (let i = 0, len = arr.length; i < len; i++) {
    newArray.indexOf(arr[i]) === -1 && newArray.push(arr[i])
    // !newArray.includes(arr[i]) && newArray.push(arr[i])
  }
  return newArray;
}
12345678

测试结果:
测试结果图
结果描述:
  for 也可以替换为 for of,虽然for of循环比for慢,但是for of直接返回元素本身,而不需要通过下标取数组数据,for in就不需要考虑了,同样返回下标,却比for慢了将近1万倍。不过for in可以遍历对象,这是其他循环比不了的。

  处理1万以内数据效率很高,10万条时,就需要几秒了。百万页面虽未直接崩溃,等待几分钟还未出结果,不过比上面双重循环效率高。indexOfincludes效率相同,只是返回值不一样。考虑到indexOf兼容性强于includes,推荐使用indexOf,当然写法上includes更加简洁。其实这种方法和上方的双重循环是一样的,因为indexOfincludes都是内部循环从数据下标0处开始循环查询,数据越靠数组后方,查询耗时越长,因为循环次数越多。

方法效率分析:
  1.经测试,indexOfincludes效率比的for循环判断值快了一倍左右,所以虽然实际上都是双重循环,但是整体效率高于双重for循环。
  2.即使在千万级的数据下循环加push耗时也不多,2千万次循环加push耗时不超过200毫秒。
  3.主要耗时还是在indexOfincludes判断数据是否重复这一点上,千万级的数据,如果要判断数据是否重复,不重复的数据要从头循环到尾,耗时非常明显。重复数据越少,耗时越多。

3.filter 加 indexOf

方法解释:
  通过indexOf判断此元素第一次出现的位置与当前的元素的index是否相同来去重。

去重代码:

function distinct(arr) {
  return arr.filter((item, i) => {
    return arr.indexOf(item) === i
  });
}
12345

测试结果:
测试结果图
结果描述:
  在效率稍上低于forindexOf的方法,数据量重复较少的情况与forindexOf处理效率上差不多,但数据量多的时候效率就有了明显的差别,同样在千万级的数据下无法处理。

方法效率分析:
  1.此方法本质上与上述两种一样,都是双重循环,同样使用了indexOf,主要的效率损耗就在个上面。
  2.经测试filter都返回false比都返回true要快,也就是重复越多越快,这就引起我们猜想,返回true类似于push了新数据到新数组。
  3.重复量越大,与forindexOf去重差距就越明显,数组filter方法效率明显要低于for循环(最后有纯粹的循环效率耗时对比)。

4.使用sort排序后去重

方法解释:
  利用sort排序,使相同元素相邻排列,通过判断当前下标与前一个下标元素是否相同从而插入新数据。我见过有人用当前下标与下一个下标元素判断,但是那种方法最后一个元素是undefined时,会造成undefined无法被判断为不重复的元素,要解决这个问题就会造成多的判断,以至于效率下降。sort排序会更改原数组,如果不想更改可以用concat()拷贝一份,如:var newArr = arr.concat()原为数组拼接,不传入数据相当于复刻一份。

去重代码:

function distinct(arr) {
  arr.sort((a, b) => a - b)
  var arrry = [arr[0]];
  for (var i = 1, len = arr.length; i < len; i++) {
    if (arr[i] !== arr[i - 1]) {
      arrry.push(arr[i]);
    }
  }
  return arrry;
}
12345678910

测试结果:
测试结果图
结果描述:
  使用sort排序后去重效率有了显著的提升,数据1百万也能在1秒内处理完。即使1千万也能勉强处理。不过当前配置电脑处理超过2千万的数据,会进入断点提示Paused before potential out-of-memory crash(在潜在的内存不足崩溃之前暂停)。在去重数值类型数据上sort排序去重效率有很大提升。
方法效率分析:
  1.利用了sort排序,主要计算时间就在排序上。如果是顺序的数值类型数组,在sort排序上所需时间就极少,经测试,这种数据即使1千万条、重复20%,也能在1秒内处理完。
  2. 这种方法也能去重其他类型数据,只需要把sort排序传入的函数去掉就行。不过在数据处理的效率上就比较差了,10万数据时就已经接近1秒钟了,100万也只能勉强处理,千万就需要用分钟计算了。

5.sort 加 reduce

方法解释:
  使用sort排序后,利用reduce特性,对比新数组最后一个元素与循环到的当前元素是否相等,不相等就插入数据。

去重代码:

function distinct(arr) {
  arr.sort((a, b) => a - b)
  return arr.reduce((newArr, current) => {
    if (newArr[newArr.length - 1] !== current) {
      newArr.push(current);
    }
    return newArr;
  }, [arr[0]]);
}
123456789

测试结果:
测试结果图
结果描述:
  此方法与上面一种方法效率相似,数据较小时(10万以内),差异并不大,数据较大时能看出差异。同样当前配置电脑处理超过2千万的数据,会进入断点提示Paused before potential out-of-memory crash(在潜在的内存不足崩溃之前暂停)

方法效率分析:
  1.与上一个方法一样利用了sort排序,主要计算时间就在排序上。
  2.此方法与上面相比差异不大,虽然reduce循环比for循环慢(后面有纯粹循环耗时排行),但在取值对比上面稍快。

6.利用对象key唯一(hasOwnProperty)

方法解释:
  对象key具有唯一性,通过给对象key赋值、取值判断元素是否重复,不重复就push数据到新数组,重复就跳过。

去重代码:

function distinct(arr) {
  var newArrry = [];
  var obj = {};
  for (var i = 0, len = arr.length; i < len; i++) {
    if (obj[arr[i]] !== 1) { // obj.hasOwnProperty(arr[i]) 也可以
      newArrry.push(arr[i])
      obj[arr[i]] = 1
    }
  }
  return newArrry;
}
1234567891011

测试结果:
测试结果图
结果描述:
  此方法计算速度还不错,与sort排序后去重效率相当,同样是超过2千万数据后会进入断点(同上)。不过对象属性不重复有比较大的问题就是
  1.true"true"在设为对象key时,值是一样的。(解决方法 使用 typeof+key
  2.无法设置复杂类型数据为key,结果key只能为[object Object](解决方法 使用 typeof+toString
处理的方法过多会造成效率的下降,因此不再此方法上多下功夫,如果数据类型明确,也可以使用这种方法。

方法效率分析:
  1.对象属性的存取需要消耗比较多的时间(利用hasOwnProperty判断属性是否存在效率也是一样)。
  2.剩余少部分时间消耗在循环和push数据上。
  3.数据是短字符串的情况下,此方法效率还能提升5倍左右。

7.使用Map数据结构

方法解释:
  与对象key唯一去重方法一致,也是通过getset数据判断元素是否重复,也可以使用has判断。

去重代码:

function distinct(arr) {
  const newArray = [];
  const newMap = new Map();
  for (let i = 0, len = arr.length; i < len; i++) {
    if (!newMap.get(arr[i])) { // newMap.has(arr[i])
      newMap.set(arr[i], 1);
      newArray.push(arr[i]);
    }
  }
  return newArray;
}
1234567891011

测试结果:
测试结果图
结果描述:
  利用Map数据结构不重复,处理效率还不错,目前效率最高的一种去重方案,不会打乱数据,不会因数据类型问题不好处理。目前只测试到1千万数据,2千万开始本机配置极易进入断点(同上)

方法效率分析:
  1.此方法时间也主要损耗在Map数据的存与取上面,不过效率比对象存取要高。

8.使用Set

方法解释:
  最简单的方法,通过new 一个 Set对象(只能存不同数据),放入重复数据的数组,再解构出来。

去重代码:

function distinct(arr) {
  return [...new Set(arr)];
}
123

测试结果:
测试结果图
结果描述:
  es6 提供的Set使用方法最简单,达到的效果也很喜人,目前效率与利用Map去重效率相当,不过考虑到Set兼容性,只能兼容到IE11,并且IE11不支持Array.from,以及解构。在不考虑IE兼容的情况下推荐使用Set

方法效率分析:
  Set去重方法,全部由Set数据结构不重复特性处理,没有具体耗时地方,整个方法就是耗时处。

总结推荐

  1.首先在不考虑IE兼容的情况下推荐使用Set去重,可以看到每个去重方法具体效率都跟数据量、重复量相关。当然有的也跟数据类型相关,比如使用sort排序去重,2.如果是有序的数值,sort排序去重无疑是最快的,兼容性也很好。如果能确定需要3.去重的数据类型是简单字符串,推荐使用对象key唯一去重,经测试,在数据是短字符串的情况下,对象key唯一的去重方式在效率上还能提升5倍以上。如果数据类型比较复杂,而又不需要兼容IE10以下,4.推荐使用Map数据唯一去重。以上所有测试结果都能看到,重复量越大,处理速度越快,反而重复得越少,需要处理的时间就越长。选择去重方案也需要考虑当前项目中是否有使用babel工具,即使用了兼容性不好的SetMap方法,babel也会打包为ES5语法。然而并不知道具体会打包成怎样去重,所以上诉方法都请视项目情况使用。

循环效率排行

  只论循环效率,不考虑内容,看看循环具体排行如何。

var arr = Array.from(new Array(10000000)); // 创建1千万条数据的数组

console.time('耗时')
// 循环体
console.timeEnd('耗时')

for         // 耗时: 6.65283203125ms - 7.085205078125ms
while         // 耗时:19.105712890625ms - 19.453857421875ms
do while    // 耗时:18.89697265625ms - 19.087890625ms
for of         // 耗时:102.4921875ms - 103.44921875ms
forEach()     // 耗时:103.834228515625ms - 104.614990234375ms
filter()    // 耗时:109.2978515625ms - 114.50390625ms
reduce()     // 耗时:113.99609375ms - 116.65625ms
map()         // 耗时:140.9560546875ms - 143.347900390625ms
for in         // 耗时:2094.56201171875ms - 2811.3017578125ms

12345678910111213141516

数组的方法还有很多就不一一列出来了
可以去此处参考数组对象方法
Array 对象

结语

  说实话,网上虽说js去重方法一大堆,但是不管怎么拼凑其实就那几种类型。也见过用递归方式去重的方法,不过效率实在太差,数据量稍微大一点就报错。以上所有数据与测试皆是本人实测,在不同电脑、系统、浏览器上会有明显差异。

看在花了大量时间测试的情况下,可以点个赞哦,如果错误欢迎指出。