桂歌 發表於 2020-5-24 15:17:00

JavaScript数组常见用法

<p>最近做一个项目中做一个竞猜游戏界面,游戏规则和彩票是一样的。在实现“机选一注”,“机选五注”的时候遇到数组的一些操作,例如产生['01', '02' ... '35']这样的数组,随机抽取不重复的元素重新组成数组等问题。回想这类问题在平时项目中遇到的机会非常多,何不归纳一下JavaScript数组的一些知识点,以供平时工作参考。</p>
<p>JavaScript提供的数组非常灵活,相关的api也很丰富,例如fill,map,filter,sort等等,极大地方便了程序编写。这里不介绍这些基本的api,而是通过工作中常用的使用场景来展示数组的强大。</p>
<h1>1.归纳计算</h1>
<p>在一个分页表格中比如订单表,要求根据订单金额展示这一页的订单总金额。很多时候后端开发偷懒,把这种计算推给前端,可以使用reduce轻松实现个功能,代码如下。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> orders =<span style="color: rgba(0, 0, 0, 1)"> [
    {
      userName: </span>'Anna'<span style="color: rgba(0, 0, 0, 1)">,
      books: </span>'Bible'<span style="color: rgba(0, 0, 0, 1)">,
      money: </span>21.2<span style="color: rgba(0, 0, 0, 1)">
    },
    {
      userName: </span>'Bob'<span style="color: rgba(0, 0, 0, 1)">,
      books: </span>'War and peace'<span style="color: rgba(0, 0, 0, 1)">,
      money: </span>26.5<span style="color: rgba(0, 0, 0, 1)">
    },
    {
      userName: </span>'Alice'<span style="color: rgba(0, 0, 0, 1)">,
      books: </span>'The Lord of the Rings'<span style="color: rgba(0, 0, 0, 1)">,
      money: </span>18.4<span style="color: rgba(0, 0, 0, 1)">
    }
];
let total </span>= orders.reduce((acc, curr) =&gt; {<span style="color: rgba(0, 0, 255, 1)">return</span> acc + curr.money}, 0<span style="color: rgba(0, 0, 0, 1)">);
console.log(total);</span></pre>
</div>
<p>在vue组件中,可以直接使用reduce表达式计算表格某一列的归纳总和,很方便,示例代码如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">tbody</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">tr </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="header-tr"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>品名<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>批号<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>规格<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>等级<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>生产入库(KG)<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>退货入库(KG)<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>返修入库(KG)<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>返修投料(KG)<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>出库(KG)<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>库存结存(件)<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>库存结存重量(KG)<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>期初结存(件)<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>期初结存重量(KG)<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">tr</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">template </span><span style="color: rgba(255, 0, 0, 1)">v-for</span><span style="color: rgba(0, 0, 255, 1)">="(item, key) in tableData"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">template </span><span style="color: rgba(255, 0, 0, 1)">v-for</span><span style="color: rgba(0, 0, 255, 1)">="obj in item"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">tr</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{key}}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{obj.batchNo}}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{obj.spec}}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{obj.level}}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{obj.productionInbound}}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{obj.refundInbound}}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{obj.reworkInbound}}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{obj.reworkFeeding}}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{obj.outbound}}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{obj.monthlyBalanceCount}}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{obj.monthlyBalanceWeight}}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{obj.preMonthlyBalanceCount}}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{obj.preMonthlyBalanceWeight}}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">td</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">tr</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">template</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">tr</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th </span><span style="color: rgba(255, 0, 0, 1)">colspan</span><span style="color: rgba(0, 0, 255, 1)">="3"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{key}}小计<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(255, 0, 0, 1)">&amp;nbsp;</span><span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{ item.reduce((acc, curr) =&gt; acc + curr.productionInbound, 0) }}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{ item.reduce((acc, curr) =&gt; acc + curr.refundInbound, 0) }}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{ item.reduce((acc, curr) =&gt; acc + curr.reworkInbound, 0) }}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{ item.reduce((acc, curr) =&gt; acc + curr.reworkFeeding, 0) }}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{ item.reduce((acc, curr) =&gt; acc + curr.outbound, 0) }}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{ item.reduce((acc, curr) =&gt; acc + curr.monthlyBalanceCount, 0) }}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{ item.reduce((acc, curr) =&gt; acc + curr.monthlyBalanceWeight, 0) }}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{ item.reduce((acc, curr) =&gt; acc + curr.preMonthlyBalanceCount, 0) }}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>{{ item.reduce((acc, curr) =&gt; acc + curr.preMonthlyBalanceWeight, 0) }}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">th</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
          <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">tr</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">template</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<h1>2.快速生成数组</h1>
<p>工作中前端进度一般是先于后端的,前端画页面的时候后端服务一般还没有写好,这时前端要自己生成一些数据把页面先做起来。有人可能会说用mock,但是小项目引用mock就太麻烦了。这时就要自己先生成一些数据,最常见的就是生成一个对象列表。下面就来讨论生成数据的方式。</p>
<h2>2.1&nbsp;Array(length)&amp;Array.fill()&amp;Array.map()</h2>
<p>构造函数Array()有两个重载:</p>
<p><strong>new Array(element0, element1[, ...[, elementN]])</strong>:根据给定元素生成一个javascript数组,这些元素是逗号分割的。<br><strong>new Array(arrayLength)</strong>:arrayLength是一个范围在0到2<sup>32</sup>-1之间的整数,这时方法返回一个长度为arrayLength的数组对象,注意数组此时没有包含任何实际的元素,不是undefined,也不是null,使用console.log()打印出来是empty。如果传入的arrayLength不满足上面条件,抛出RangeError错误。</p>
<p>使用Array(arrayLength)获取到空数组之后,使用Array.fill()方法给数组填充初始值,再使用Array.map()方法给数组元素生成有意义的值。</p>
<div class="cnblogs_code">
<pre>console.time("arr1"<span style="color: rgba(0, 0, 0, 1)">);
let arr1 </span>= Array(10).fill(0).map((value, index) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> ++<span style="color: rgba(0, 0, 0, 1)">index;
});
console.timeEnd(</span>"arr1"<span style="color: rgba(0, 0, 0, 1)">);
console.log(arr1);</span></pre>
</div>
<p>输出结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200518090042353-1055811504.png" alt="">&nbsp;</p>
<h2>&nbsp;2.2&nbsp;Array()&amp;Array.from()</h2>
<p><strong>Array.from</strong>:方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。代码如下:</p>
<div class="cnblogs_code">
<pre>console.time("arr2"<span style="color: rgba(0, 0, 0, 1)">);
let arr2 </span>= Array.from(<span style="color: rgba(0, 0, 255, 1)">new</span> Array(10), (value, index) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> ++<span style="color: rgba(0, 0, 0, 1)">index;
});
console.timeEnd(</span>"arr2"<span style="color: rgba(0, 0, 0, 1)">);
console.log(arr2);</span></pre>
</div>
<p>&nbsp;</p>
<p>执行结果如下:</p>
<p>&nbsp;<img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200518085920886-1019636205.png" alt=""></p>
<h2>2.3&nbsp;使用递归</h2>
<p>使用了递归和立即执行函数来生成数组。</p>
<div class="cnblogs_code">
<pre>console.time("arr3"<span style="color: rgba(0, 0, 0, 1)">)
let arr3 </span>= (<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> wallace(i) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> (i &lt; 1) ? [] : wallace(i - 1<span style="color: rgba(0, 0, 0, 1)">).concat(i);
})(</span>10<span style="color: rgba(0, 0, 0, 1)">);
console.timeEnd(</span>"arr3");</pre>
</div>
<p>执行结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200518090327740-1106574620.png" alt=""></p>
<h2>2.4&nbsp;使用尾递归</h2>
<p>相对递归来说,尾递归效率更高。</p>
<div class="cnblogs_code">
<pre>console.time("arr4"<span style="color: rgba(0, 0, 0, 1)">)
let arr4 </span>= (<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> mistake(i, acc) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> (i &lt; 10) ? mistake(i + 1<span style="color: rgba(0, 0, 0, 1)">, acc.concat(i)) : acc;
})(</span>1<span style="color: rgba(0, 0, 0, 1)">, []);
console.timeEnd(</span>"arr4"<span style="color: rgba(0, 0, 0, 1)">)
console.log(arr4);</span></pre>
</div>
<p>执行结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200518090458663-589311646.png" alt=""></p>
<h2>2.5&nbsp;使用ES6中的Generator</h2>
<div class="cnblogs_code">
<pre>console.time("arr5"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">function</span>*<span style="color: rgba(0, 0, 0, 1)"> mistake(i) {
    yield i;
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (i &lt; 10<span style="color: rgba(0, 0, 0, 1)">) {
      yield</span>* mistake(i + 1<span style="color: rgba(0, 0, 0, 1)">);
    }
}
let arr5 </span>= Array.from(mistake(1<span style="color: rgba(0, 0, 0, 1)">));
console.timeEnd(</span>"arr5"<span style="color: rgba(0, 0, 0, 1)">);
console.log(arr5);</span></pre>
</div>
<p>执行结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200518090739035-2121673461.png" alt="">&nbsp;</p>
<h2>2.6&nbsp;使用apply和类数组对象</h2>
<div class="cnblogs_code">
<pre>console.time("arr6"<span style="color: rgba(0, 0, 0, 1)">);
let arr6 </span>= Array.apply(<span style="color: rgba(0, 0, 255, 1)">null</span>, {length: 10}).map((value, index) =&gt; index + 1<span style="color: rgba(0, 0, 0, 1)">);
console.timeEnd(</span>"arr6"<span style="color: rgba(0, 0, 0, 1)">);
console.log(arr6);</span></pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200518091504271-1918884220.png" alt="">&nbsp;</p>
<h1>3.数组去重</h1>
<h2>3.1&nbsp;对象属性</h2>
<p>使用对象属性不重名的特性。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> arr = ['qiang','ming','tao','li','liang','you','qiang','tao'<span style="color: rgba(0, 0, 0, 1)">];
console.time(</span>"nonredundant1"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> nonredundant1 = Object.getOwnPropertyNames(arr.reduce(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(seed, item, index) {
    seed </span>=<span style="color: rgba(0, 0, 0, 1)"> index;
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> seed;
},{}));
console.timeEnd(</span>"nonredundant1"<span style="color: rgba(0, 0, 0, 1)">);
console.log(nonredundant1);</span></pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200518092036225-494940510.png" alt="">&nbsp;</p>
<h2>3.2&nbsp;使用Set</h2>
<p>set是一种类似数组的结构,但是set成员中没有重复的值。set()函数可以接受一个数组或者类数组的参数,生成一个set对象。而Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object和可遍历iterable)的对象包括 ES6 新增的数据结构 Set 和 Map)。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> arr = ['qiang','ming','tao','li','liang','you','qiang','tao'<span style="color: rgba(0, 0, 0, 1)">];
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> unique (arr) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> Array.from(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Set(arr))
}
console.time(</span>"nonredundant2"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> nonredundant2 =<span style="color: rgba(0, 0, 0, 1)"> unique(arr);
console.timeEnd(</span>"nonredundant2"<span style="color: rgba(0, 0, 0, 1)">);
console.log(nonredundant2);</span></pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200518125036886-276660493.png" alt=""></p>
<h2>3.3&nbsp;使用for循环和splice</h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> unique(arr) {
    </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> i = 0; i &lt; arr.length; i++<span style="color: rgba(0, 0, 0, 1)">) {
      </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> j = i + 1; j &lt; arr.length; j++<span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (arr == arr) {         <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">第一个等同于第二个,splice方法删除第二个</span>
                arr.splice(j, 1<span style="color: rgba(0, 0, 0, 1)">);
                j</span>--<span style="color: rgba(0, 0, 0, 1)">;
            }
      }
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> arr;
}
console.time(</span>"nonredundant3"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> arr = ['qiang', 'ming', 'tao', 'li', 'liang', 'you', 'qiang', 'tao'<span style="color: rgba(0, 0, 0, 1)">];
</span><span style="color: rgba(0, 0, 255, 1)">var</span> nonredundant3 =<span style="color: rgba(0, 0, 0, 1)"> unique(arr);
console.timeEnd(</span>"nonredundant3"<span style="color: rgba(0, 0, 0, 1)">);
console.log(nonredundant3);</span></pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200518094116318-1895007543.png" alt=""></p>
<h2>3.4&nbsp;使用indexOf判断去重</h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> unique(arr) {
    </span><span style="color: rgba(0, 0, 255, 1)">var</span> array =<span style="color: rgba(0, 0, 0, 1)"> [];
    </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> i = 0; i &lt; arr.length; i++<span style="color: rgba(0, 0, 0, 1)">) {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (array .indexOf(arr) === -1<span style="color: rgba(0, 0, 0, 1)">) {
            array .push(arr)
      }
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> array;
}
</span><span style="color: rgba(0, 0, 255, 1)">var</span> arr = ['qiang', 'ming', 'tao', 'li', 'liang', 'you', 'qiang', 'tao'<span style="color: rgba(0, 0, 0, 1)">];
console.time(</span>"nonredundant4"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> nonredundant4 =<span style="color: rgba(0, 0, 0, 1)"> unique(arr);
console.timeEnd(</span>"nonredundant4"<span style="color: rgba(0, 0, 0, 1)">);
console.log(nonredundant4);</span></pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200518125354231-228777624.png" alt=""></p>
<h2>3.5&nbsp;使用sort排序去重</h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> unique(arr) {
    arr </span>=<span style="color: rgba(0, 0, 0, 1)"> arr.sort()
    </span><span style="color: rgba(0, 0, 255, 1)">var</span> arrry = ];
    </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> i = 1; i &lt; arr.length; i++<span style="color: rgba(0, 0, 0, 1)">) {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (arr !== arr) {
            arrry.push(arr);
      }
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> arrry;
}

</span><span style="color: rgba(0, 0, 255, 1)">var</span> arr = ['qiang', 'ming', 'tao', 'li', 'liang', 'you', 'qiang', 'tao'<span style="color: rgba(0, 0, 0, 1)">];
console.time(</span>"nonredundant5"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> nonredundant5 =<span style="color: rgba(0, 0, 0, 1)"> unique(arr);
console.timeEnd(</span>"nonredundant5"<span style="color: rgba(0, 0, 0, 1)">);
console.log(nonredundant5);</span></pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200518130002938-506881449.png" alt="">&nbsp;</p>
<h2>3.6&nbsp;使用filter</h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> unique(arr) {
    </span><span style="color: rgba(0, 0, 255, 1)">var</span> obj =<span style="color: rgba(0, 0, 0, 1)"> {};
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> arr.filter(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(item, index, arr){
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> obj.hasOwnProperty(<span style="color: rgba(0, 0, 255, 1)">typeof</span> item + item) ? <span style="color: rgba(0, 0, 255, 1)">false</span> : (obj[<span style="color: rgba(0, 0, 255, 1)">typeof</span> item + item] = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">)
    })
}
</span><span style="color: rgba(0, 0, 255, 1)">var</span> arr = ['qiang', 'ming', 'tao', 'li', 'liang', 'you', 'qiang', 'tao'<span style="color: rgba(0, 0, 0, 1)">];
console.time(</span>"nonredundant6"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> nonredundant6 =<span style="color: rgba(0, 0, 0, 1)"> unique(arr);
console.timeEnd(</span>"nonredundant6"<span style="color: rgba(0, 0, 0, 1)">);
console.log(nonredundant6);</span></pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200518130611950-1786034980.png" alt=""></p>
<h2>3.7&nbsp;使用Map数据结构去重</h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> unique(arr) {
    let map </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Map();
    let array </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Array();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 数组用于返回结果</span>
    <span style="color: rgba(0, 0, 255, 1)">for</span> (let i = 0; i &lt; arr.length; i++<span style="color: rgba(0, 0, 0, 1)">) {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (map.has(arr)) {<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果有该key值</span>
            map.set(arr, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
      } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
            map.set(arr, </span><span style="color: rgba(0, 0, 255, 1)">false</span>);   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果没有该key值</span>
<span style="color: rgba(0, 0, 0, 1)">            array.push(arr);
      }
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> array;
}

</span><span style="color: rgba(0, 0, 255, 1)">var</span> arr = ['qiang', 'ming', 'tao', 'li', 'liang', 'you', 'qiang', 'tao'<span style="color: rgba(0, 0, 0, 1)">];
console.time(</span>"nonredundant7"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> nonredundant7 =<span style="color: rgba(0, 0, 0, 1)"> unique(arr);
console.timeEnd(</span>"nonredundant7"<span style="color: rgba(0, 0, 0, 1)">);
console.log(nonredundant7);</span></pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200518131134557-458611735.png" alt=""></p>
<h2>3.8&nbsp;使用reduce和include去重</h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> unique(arr){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> arr.reduce((prev,cur) =&gt; prev.includes(cur) ?<span style="color: rgba(0, 0, 0, 1)"> prev : [...prev,cur],[]);
}
</span><span style="color: rgba(0, 0, 255, 1)">var</span> arr = ['qiang', 'ming', 'tao', 'li', 'liang', 'you', 'qiang', 'tao'<span style="color: rgba(0, 0, 0, 1)">];
console.time(</span>"nonredundant8"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> nonredundant8 =<span style="color: rgba(0, 0, 0, 1)"> unique(arr);
console.timeEnd(</span>"nonredundant8"<span style="color: rgba(0, 0, 0, 1)">);
console.log(nonredundant8);</span></pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200519091240561-1003712062.png" alt=""></p>
<h1>4. 数组随机选取</h1>
<p>这个需求在实际开发中也很常见,比如彩票随机一注,随机五注,机动车号牌随机选一个等等。</p>
<h2>4.1 大于等于0小于1的随机数</h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getRandom() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Math.random();
}</span></pre>
</div>
<p>&nbsp;</p>
<h2>4.2 两数之间的随机数</h2>
<p>返回一个在指定值之间的随机数,这个随机数大于等于min,小于max。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getRandomArbitrary(min, max) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> Math.random() * (max - min) +<span style="color: rgba(0, 0, 0, 1)"> min;
}</span></pre>
</div>
<p>&nbsp;</p>
<h2>4.3 两数之间的随机整数</h2>
<p>返回一个在指定值之间的随机整数,这个值大于等于min(如果min不是整数,则大于等于min的向上取整数),且小于max(不等于)。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getRandomInt(min, max) {
min </span>=<span style="color: rgba(0, 0, 0, 1)"> Math.ceil(min);
max </span>=<span style="color: rgba(0, 0, 0, 1)"> Math.floor(max);
</span><span style="color: rgba(0, 0, 255, 1)">return</span> Math.floor(Math.random() * (max - min)) + min; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">不含最大值,含最小值</span>
}</pre>
</div>
<p>&nbsp;</p>
<h2>4.4 两数之间的随机整数,包含两数</h2>
<p>上面的getRandomInt()方法返回的随机数包含了最小值,但不包含最大值,下面的方法同时包含最小值和最大值。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getRandomIntInclusive(min, max) {
min </span>=<span style="color: rgba(0, 0, 0, 1)"> Math.ceil(min);
max </span>=<span style="color: rgba(0, 0, 0, 1)"> Math.floor(max);
</span><span style="color: rgba(0, 0, 255, 1)">return</span> Math.floor(Math.random() * (max - min + 1)) + min; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">含最大值,含最小值 </span>
}</pre>
</div>
<h2>4.5 Math.random()的随机问题</h2>
<p>这种方式是使用Array.sort()和Math.random()结合的方法,Math.random()返回的是一个0-1之间(不包括1)的伪随机数,注意这不是真正的随机数。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> letter = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'<span style="color: rgba(0, 0, 0, 1)">];
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> shuffle1(arr) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> arr.sort(() =&gt; 0.5 -<span style="color: rgba(0, 0, 0, 1)"> Math.random())
}
console.time(</span>"shuffle1"<span style="color: rgba(0, 0, 0, 1)">);
letter </span>=<span style="color: rgba(0, 0, 0, 1)"> shuffle1(letter);
console.timeEnd(</span>"shuffle1"<span style="color: rgba(0, 0, 0, 1)">);
console.log(letter);</span></pre>
</div>
<p>这种方式并不是真正的随机,来看下面的例子。对这个10个字母数组排序1000次,假设这个排序是随机的话,字母a在排序后的数组中每个位置出现的位置应该是1000/10=100,或者说接近100次。看下面的测试代码:</p>
<div class="cnblogs_code">
<pre>let n = 1000<span style="color: rgba(0, 0, 0, 1)">;
let count </span>= (<span style="color: rgba(0, 0, 255, 1)">new</span> Array(10)).fill(0<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (let i = 0; i &lt; n; i++<span style="color: rgba(0, 0, 0, 1)">) {
    let letter </span>= ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'<span style="color: rgba(0, 0, 0, 1)">];
    letter.sort(() </span>=&gt; Math.random() - 0.5<span style="color: rgba(0, 0, 0, 1)">);
    count++<span style="color: rgba(0, 0, 0, 1)">
}
console.log(count);</span>&nbsp;</pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200521095757512-1891181489.png" alt=""></p>
<p>可以看出元素a的位置在0到9出现的次数并不是接近100的。</p>
<p>原因有两点:</p>
<ol>
<li>Math.random()方法产生的伪随机数并不是在0到1之间均匀分布,不能提供像密码一样安全的随机数字。</li>
<li>Array.prototype.sort(compareFunction)方法中的compareFunction(a, b)回调必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。</li>
</ol>
<p>这里sort(() =&gt; 0.5 - Math.random())没有输入,跟谈不上返回相同的结果,所以这个方法返回的结果不是真正的数组中的随机元素。&nbsp;</p>
<h2>4.6 随机值排序</h2>
<p>既然(a, b) =&gt; Math.random() - 0.5 的问题是不能保证针对同一组 a、b 每次返回的值相同,那么我们不妨将数组元素改造一下,比如将元素'a'改造为{&nbsp;value: 'a', range: Math.random() },数组变成[{&nbsp;value: 'a', range:&nbsp;0.10497314648454847 }, {&nbsp;value: 'b', range:&nbsp;0.6497386423992171 }, ...],比较的时候用这个range值进行比较,这样就满足了Array.sort()的比较条件。代码如下:</p>
<div class="cnblogs_code">
<pre>let letter = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'<span style="color: rgba(0, 0, 0, 1)">];
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> shuffle2(arr) {
    let new_arr </span>= arr.map(i =&gt;<span style="color: rgba(0, 0, 0, 1)"> ({value: i, range: Math.random()}));
    new_arr.sort((a, b) </span>=&gt; a.r -<span style="color: rgba(0, 0, 0, 1)"> b.r);
    arr.splice(</span>0, arr.length, ...new_arr.map(i =&gt;<span style="color: rgba(0, 0, 0, 1)"> i.value));
}
console.time(</span>"shuffle2"<span style="color: rgba(0, 0, 0, 1)">);
letter </span>=<span style="color: rgba(0, 0, 0, 1)"> shuffle2(letter);
console.timeEnd(</span>"shuffle2"<span style="color: rgba(0, 0, 0, 1)">);
console.log(shuffle2);</span>&nbsp;</pre>
</div>
<p>输出结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200521095351811-247120059.png" alt=""></p>
<p>&nbsp;我们再使用上面的方式测试一下,看看元素a元素是不是随机分布的。</p>
<div class="cnblogs_code">
<pre>let n = 1000, count = (<span style="color: rgba(0, 0, 255, 1)">new</span> Array(10)).fill(0<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (let i = 0; i &lt; n; i++<span style="color: rgba(0, 0, 0, 1)">) {
    let letter </span>= ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'<span style="color: rgba(0, 0, 0, 1)">];
    letter </span>=<span style="color: rgba(0, 0, 0, 1)"> shuffle2(letter)
    count++<span style="color: rgba(0, 0, 0, 1)">
}
console.log(count);</span>&nbsp;</pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200521100523068-1417516130.png" alt=""></p>
<p>从这里可以看出,元素a在位置0到9出现的次数是接近100的,也就是说元素a是随机分布的,其他的元素也是,这时再从这个新数组中截取前几个元素就是想要的数组了。</p>
<h2>4.7 洗牌算法</h2>
<p>上面的sort算法,虽然满足了随机性的需求,但是性能上并不是很好,很明显为了达到随机目的把简单数组变成了对象数组,最后又从排序后的数组中获取这个随机数组,明显走了一些弯路。</p>
<p>洗牌算法可以解决随机性问题,洗牌算法的步骤如下:</p>
<ol>
<li>数组arr,有n个元素,存放从1到n的数值;</li>
<li>生成一个从0到n-1的随机数x;</li>
<li>输出arr下标为x的元素,即第一个随机数;</li>
<li>将arr的尾元素和下标为x的元素值互换;</li>
<li>同步骤2,生成一个从0到n-2的随机数x;</li>
<li>输出arr下标为x的数组,第二个随机数;</li>
<li>将arr倒数第二个元素和下标为x的元素互换;</li>
<li>重复执行直至输出m个数为止;</li>
</ol>
<p>洗牌算法是真的随机的吗,换言之洗牌算法真的可以随机得到n个元素中m个吗?下面拿一个只有5个元素的数组来说明。</p>
<p>&nbsp;数组有5个元素,如下图。</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522172751174-1101823711.png" alt="">&nbsp;</p>
<p>从5个元素随机抽出一个元素和最后一个换位,假设抽到3,概率是1/5,如下图。注意其他任意4个元素未被抽到的概率是4/5。最终3出现在最后一位的概率是1/5。</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522172834307-287550082.png" alt="">&nbsp;</p>
<p>将抽到的3和最后一位的5互换位置,最后一位3就确定了,如下图:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522173324813-796866115.png" alt="">&nbsp;</p>
<p>再从前面不确定的4个元素随机抽一个,这里注意要先考虑这4个元素在第一次未被抽到的概率是4/5,再考虑本次抽到的概率是1/4,然后乘一下得到1/5。注意其他任意3个未被抽到的概率是3/4。5出现在倒数第二位的概率是4/5*1/4=1/5如下图:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522173009533-1809698895.png" alt=""></p>
<p>现在最后2个元素确定了,从剩下的3个元素中任意抽取一个,概率是1/3,身下任意2个未被抽到的概率是2/3,但是要考虑上一次未被抽到的概率是3/4,以及上上一次未被抽到的概率是4/5,于是最终1出现在倒数第三位的概率是1/3*3/4*4/5=1/5。</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522173730037-677767165.png" alt="">&nbsp;</p>
<p>现在倒数3个元素已经确定,剩下的2个元素中任意取一个,概率是1/2,但是要考虑上一次未被抽到的概率是2/3,上上一次未被抽到的概率是3/4,上上上一次未被抽到的概率是4/5,最终4出现在倒数第4位的概率是1/2*2/3*3/4*4/5=1/5。</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522174802027-1778661386.png" alt="">&nbsp;</p>
<p>最后还剩下一个2,它出现在倒数第5位的概率肯定也是1/5。不嫌啰嗦的话可以继续看下去。</p>
<p>现在倒数4个元素已经确定,剩下1个元素中任意取一个,概率是1,但要考虑上一次未被抽中的概率是1/2,上上一次未被抽中的概率是2/3,上上上一次未被抽中的概率是3/4,上上上上一次未被抽中的概率是4/5,于是2出现在倒数5位置的概率是1*1/2*2/3*3/4*4/5=1/5。</p>
<p>有了算法,下面给出洗牌算法的代码:</p>
<div class="cnblogs_code">
<pre>let letter = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'<span style="color: rgba(0, 0, 0, 1)">];
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> shuffle3(arr) {
    let i </span>=<span style="color: rgba(0, 0, 0, 1)"> arr.length, t, j;
    </span><span style="color: rgba(0, 0, 255, 1)">while</span><span style="color: rgba(0, 0, 0, 1)"> (i) {
      j </span>= Math.floor(Math.random() * (i--)); <span style="color: rgba(0, 128, 0, 1)">//
</span>      t =<span style="color: rgba(0, 0, 0, 1)"> arr;
      arr </span>=<span style="color: rgba(0, 0, 0, 1)"> arr;
      arr </span>=<span style="color: rgba(0, 0, 0, 1)"> t;
    }
}
console.time(</span>"shuffle3"<span style="color: rgba(0, 0, 0, 1)">);
shuffle3(letter);
console.timeEnd(</span>"shuffle3"<span style="color: rgba(0, 0, 0, 1)">);
console.log(letter)</span>&nbsp;</pre>
</div>
<p>运行结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522175453856-1723031712.png" alt="">&nbsp;</p>
<p>&nbsp;还有最后一个问题,我们来验证一下,还是和上面的方法一样,随机排序1000次,看看字母a出现在0-9个位置的概率是多少,理论上应该是1000/10=100。来看下面的代码:</p>
<div class="cnblogs_code">
<pre>let n = 1000<span style="color: rgba(0, 0, 0, 1)">;
let count </span>= (<span style="color: rgba(0, 0, 255, 1)">new</span> Array(10)).fill(0<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> shuffle3(arr) {
    let i </span>=<span style="color: rgba(0, 0, 0, 1)"> arr.length, t, j;
    </span><span style="color: rgba(0, 0, 255, 1)">while</span><span style="color: rgba(0, 0, 0, 1)"> (i) {
      j </span>= Math.floor(Math.random() * (i--)); <span style="color: rgba(0, 128, 0, 1)">//
</span>      t =<span style="color: rgba(0, 0, 0, 1)"> arr;
      arr </span>=<span style="color: rgba(0, 0, 0, 1)"> arr;
      arr </span>=<span style="color: rgba(0, 0, 0, 1)"> t;
    }
}
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (let i = 0; i &lt; n; i++<span style="color: rgba(0, 0, 0, 1)">) {
    let letter </span>= ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'<span style="color: rgba(0, 0, 0, 1)">];
    shuffle3(letter);
    count++<span style="color: rgba(0, 0, 0, 1)">
}
console.log(count);</span>&nbsp;</pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522175944538-1329197736.png" alt="">&nbsp;</p>
<p>可以看到基本上都是接近100的,可以说明洗牌算法是随机的。</p>
<h2>4.8 机选彩票</h2>
<p>最近开发做了一个模拟彩票游戏的功能,彩票有机选,其实就是随机选取,下面以双色球为例来看看实现的效果是什么样的。双色球前区从1到33个小球,后区从1到16个小球,一注彩票中前区至少选6个,后区至少选1个。这里使用洗牌算法实现,如下图:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200525195027704-1493773700.gif" alt=""></p>
<h1>5.数组扁平化</h1>
<p>数组扁平化就是把一个多维数组转换成一维的。</p>
<h2>5.1&nbsp;flat方法</h2>
<p>es6已经实现了数组的flat方法,使用方法很简单,如].flat()。flat方法可以传入一个参数表示最多处理多深的数组。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> arr1 = ];
arr1 </span>=<span style="color: rgba(0, 0, 0, 1)"> arr1.flat();
console.log(arr1); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> </span>

<span style="color: rgba(0, 0, 255, 1)">var</span> arr2 = ]];
arr2 </span>=<span style="color: rgba(0, 0, 0, 1)"> arr2.flat();
console.log(arr2); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">]</span>

<span style="color: rgba(0, 0, 255, 1)">var</span> arr3 = ]];
arr3 </span>= arr3.flat(2<span style="color: rgba(0, 0, 0, 1)">);
console.log(arr3); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> </span>

<span style="color: rgba(0, 0, 255, 1)">var</span> arr4 = ]]]];
arr4 </span>=<span style="color: rgba(0, 0, 0, 1)"> arr4.flat(Infinity);
console.log(arr4); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> </span>&nbsp;</pre>
</div>
<h2>5.2&nbsp;reduce实现</h2>
<p>上面介绍数组归纳的时候讲到过reduce,它对数组中的每个元素执行一个指定的函数,最终将结果汇总为单个返回值,然后配合concat方法合并两个数组,来实现扁平化。</p>
<div class="cnblogs_code">
<pre>    let arr = ]];
    </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> flatten1(arr) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> arr.reduce((prev, curr) =&gt; prev.concat(Array.isArray(curr) ?<span style="color: rgba(0, 0, 0, 1)"> flatten1(curr) : curr), []);
    }
    console.time(</span>"flatten1"<span style="color: rgba(0, 0, 0, 1)">);
    console.log(flatten1(arr));
    console.timeEnd(</span>"flatten1");&nbsp;</pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522193547044-1942930187.png" alt="">&nbsp;</p>
<h2>&nbsp;5.3&nbsp;toString &amp; split</h2>
<p>调用数组的toString方法,不管数组有几层,都可以将数组变为字符串并用逗号分隔,然后再使用split分隔,map还原为数组。</p>
<div class="cnblogs_code">
<pre>let arr = ]];
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> flatten2(arr) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> arr.toString().split(",").map(i =&gt;<span style="color: rgba(0, 0, 0, 1)"> Number(i));
}
console.time(</span>"flatten2"<span style="color: rgba(0, 0, 0, 1)">);
console.log(flatten2(arr));
console.timeEnd(</span>"flatten2");&nbsp;</pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522194049496-1620830037.png" alt="">&nbsp;</p>
<h2>&nbsp;5.4&nbsp;join &amp; split</h2>
<p>调用对数组调用join方法,不管数组有几层,都可以将数组变成字符串并用逗号分隔,然后使用split分隔,map还原为数组。</p>
<div class="cnblogs_code">
<pre>let arr = ]];
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> flatten3(arr) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> arr.join().split(",").map(i =&gt;<span style="color: rgba(0, 0, 0, 1)"> parseInt(i));
}
console.time(</span>"flatten3"<span style="color: rgba(0, 0, 0, 1)">);
console.log(flatten3(arr));
console.timeEnd(</span>"flatten3");&nbsp;</pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522194657289-1701590314.png" alt="">&nbsp;</p>
<h2>5.5&nbsp;递归</h2>
<p>这种方法和第一种类似,只不过是用map得到数组。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> flatten4(arr) {
    let res </span>=<span style="color: rgba(0, 0, 0, 1)"> [];
    arr.map(item </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(Array.isArray(item)) {
            res </span>=<span style="color: rgba(0, 0, 0, 1)"> res.concat(flatten4(item));
      } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
            res.push(item);
      }
    });
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> res;
}
let arr </span>= ]];
console.time(</span>"flatten4"<span style="color: rgba(0, 0, 0, 1)">);
console.log(flatten4(arr));
console.timeEnd(</span>"flatten4");&nbsp;</pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522195113356-942970519.png" alt="">&nbsp;</p>
<h2>5.6&nbsp;扩展运算符</h2>
<p>es6中的扩展运算符可以展开数组,将数组元素转换成逗号分隔的对象。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> flatten5(arr) {
    </span><span style="color: rgba(0, 0, 255, 1)">while</span> (arr.some(item =&gt;<span style="color: rgba(0, 0, 0, 1)"> Array.isArray(item))) {
      arr </span>=<span style="color: rgba(0, 0, 0, 1)"> [].concat(...arr);
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> arr;
}
let arr </span>= ]];
console.time(</span>"flatten5"<span style="color: rgba(0, 0, 0, 1)">);
console.log(flatten5(arr));
console.timeEnd(</span>"flatten5");&nbsp;</pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522195758861-393529835.png" alt="">&nbsp;&nbsp;</p>
<h2>5.7&nbsp;使用Generator函数</h2>
<p>Generator函数也可以递归调用,这种方式比较新颖。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span>*<span style="color: rgba(0, 0, 0, 1)"> flatten6(array) {
    </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (const item of array) {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (Array.isArray(item)) {
            yield</span>*<span style="color: rgba(0, 0, 0, 1)"> flatten6(item);
      } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
            yield item;
      }
    }
}
let arr </span>= ]];
console.time(</span>"flatten6"<span style="color: rgba(0, 0, 0, 1)">);
console.log(flatten6(arr));
console.timeEnd(</span>"flatten6");&nbsp;</pre>
</div>
<p>结果如下:</p>
<p><img src="https://img2020.cnblogs.com/blog/72678/202005/72678-20200522195929950-1614050728.png" alt=""></p>
<h1>6.总结</h1>
<p>数组是平时开发时最常用到的数据结构,充分了解数组的技巧以及相关的api对开发工作大有帮助,首先要做到的是了解这些知识点,然后重要的是在开发中能够使用起来,这样才能让他们迸发出生命力。本文如有错误,请大家指正。</p>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    <p style="background-position: 1% 50%; border-top: #e0e0e0 1px dashed; border-right: #e0e0e0 1px dashed; border-bottom: #e0e0e0 1px dashed; border-left: #e0e0e0 1px dashed; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 60px; background: #969696 url(&quot;https://images.cnblogs.com/cnblogs_com/lloydsheng/239039/o_copyright.gif&quot;) no-repeat 1% 50%; font-family: 微软雅黑; font-size: 12px; color: #FFFFFF">
            作者:<b><span style="font-size: 12px; color: red">Tyler Ning</span></b>
            <br>
            出处:http://www.cnblogs.com/tylerdonet/
            <br>
            本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,请微信联系<strong >冬天里的一把火
            </strong>
<div class="van-overlay" style="display: none;z-index: 1;position: fixed;top: 0;left: 0;z-index: 1;width: 100%;height: 100%;background-color: rgba(0, 0, 0, 0.7);"></div>
<imgid="pop-contect-wechat" style="display:none;width:20em;position: fixed;max-height: 100%;overflow-y: auto;transition: transform 0.3s;" src="https://files-cdn.cnblogs.com/files/tylerdonet/shouwangzhe059187.bmp"/>
      </p><br><br>
来源:https://www.cnblogs.com/tylerdonet/p/12898911.html
頁: [1]
查看完整版本: JavaScript数组常见用法