数组自动洗牌 5 次

Shuffle array automatically 5 times

我已经编写了 JavaScript 函数,用于在点击时随机播放一组 div。

  // Function to shuffle 3 divs
  shuffle = () => {
    const shuffled = this.state.divs.sort(() => Math.random() - .50);
    this.setState([...shuffled]);
  };

  // Button as an FYI
  <button onClick={this.shuffle} className="has-text-black">shuffle hats</button>

这个效果非常好,每次我点击按钮时都会随机化。

但是,我希望 div 自动 sort/shuffle 5 次,onClick。
(IE = 我不想点击 5 次,随机播放 5 次)。

执行此操作的最佳方法是什么?
(我已经搜索过但没有找到任何可以重复洗牌的元素)。

我考虑过使用异步 await/settimeout,重复 this.state.divs.sort(() => Math.random() - .50) 5 次?

更新:

要添加上下文,这里是一个codesandbox... https://codesandbox.io/s/distracted-shape-ifsiv

当我点击随机播放按钮时,你可以看到帽子只交换一次位置。不是5次。

我不明白为什么洗牌 5 次比洗牌 5 次更好或有什么不同。不管怎样,你可以像这样用一种天真的方式来做:

// Function to shuffle 3 divs
  shuffle = () => {
    const shuffled = this.state.divs.sort(() => Math.random() - .50);
    this.setState([...shuffled]);
  };

  shuffleTimesFive = () => {
     for(var i = 0; i < 5; i++) 
         this.shuffle();
  }

  // Button as an FYI
  <button onClick={this.shuffleTimesFive} className="has-text-black">shuffle hats</button>

或者更聪明的方法是使用一个带有参数的 shuffleNTimes 函数,如下所示:

  // Function to shuffle 3 divs
  shuffle = () => {
    const shuffled = this.state.divs.sort(() => Math.random() - .50);
    this.setState([...shuffled]);
  };

  shuffleNTimes = (n) => {
     for(var i = 0; i < n; i++) 
         this.shuffle();
  }

  // Button as an FYI
  <button onClick={this.shuffleNTimes.bind(this, 5)} className="has-text-black">shuffle hats</button>

我认为洗牌 1 次和 5 次效果相同,Fisher-Yates 效率更高,但保持你的方式:

  shuffle = () => {
    let shuffled = [];
    for(let i=0; i<5; i++) 
      shuffled = this.state.divs.sort(() => Math.random() - .50);
    this.setState([...shuffled]);
  };

如果您决定使用 "Fisher-Yates" 算法,您可以像这样实现它:

const shuffle = () => {
    let array = this.state.divs;
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
    this.setState([...array]);
}

正如我从您的评论中了解到的,您想制作动画,在这种情况下您不需要循环,而是可以使用 setInterval() 并重置它执行了五次。我已经写了一个关于两种洗牌方式的演示,你可以看到使用 sort() 的方法有时 returns 相同的结果,而 "Fisher–Yates" 总是重新洗牌。

<button onclick="shuffle()">Click To Shuffle</button>
<div id="1">div1</div>
<div id="2">div2</div>
<div id="3">div3</div>
<div id="4">div4</div>

<script>
//This one uses Fisher–Yates shuffle algorithm:
  const divs = [...document.querySelectorAll('div')];

  const shuffle = () => {
    let count = 0;
    const intervalId = setInterval( function() {
      for (let i = divs.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [divs[i], divs[j]] = [divs[j], divs[i]];
      }
      divs.forEach( div => document.body.appendChild(div) );
      count++;
      if(count === 5) 
        clearInterval(intervalId);
    } ,1000)
  }

</script>

<button onclick="shuffle()">Click To Shuffle</button>
<div id="1">div1</div>
<div id="2">div2</div>
<div id="3">div3</div>
<div id="4">div4</div>

<script>

  const divs = [...document.querySelectorAll('div')];

  shuffle = () => {
    let shuffled = [];
    let count = 0;
    const intervalId = setInterval( function() {
      shuffled = divs.sort(() => Math.random() - .50);
      shuffled.forEach( div => document.body.appendChild(div) );
      count++;
      if(count === 5) 
        clearInterval(intervalId);
    }, 1000 )
  };

</script>

对于你的情况,它就像:

  let divs = this.state.divs;

  const shuffle = () => {
    let count = 0;
    const intervalId = setInterval( function() {
      for (let i = divs.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [divs[i], divs[j]] = [divs[j], divs[i]];
      }
      this.setState([...divs]);
      count++;
      if(count === 5) 
        clearInterval(intervalId);
    } ,1000)
  }

这是一种可行的方法,javascript。

hats 对象被洗牌 5 次,第二个转换为 200 毫秒。

当然很简单,对象就是用来扩展的!

let hats = [
  {content: `<h6>1</h6>`},
  {content: `<h3>2</h3>`},
  {content: `<h1>3</h1>`},
  {content: `<h2>4</h2>`},
  {content: `<h4>5</h4>`}
];
let timer;

function loop5(){
  let i = 0
  clearInterval(timer)
  timer = setInterval(function(){
    shuffle()
    if (i >= 5){
      clearInterval(timer)
    } 
    i++    
  }, 200)
}

function shuffle(){
   hats.sort(() => Math.random() - 0.5)
   out.innerHTML = hats.map(e => e.content).join("")
}
div {display: flex; font-size: xx-large }
<button onclick="loop5()">shuffle hats</button>
<div id="out"></div>