1
animations = ['fadeIn','fadeInDown','slideInUp','flipInY','bounceInLeft'];

Imagine I generate random effect whenever user click something, so to achieve best experience, I would want the user to have same effect. But with

animations[ Math.floor(Math.random() * animations.length) -1];

that would happens.

How to avoid same value to appear again?

Maria Jane
  • 2,353
  • 6
  • 23
  • 39

3 Answers3

3

Two ways that i can suggest.

  1. First shuffle the array and go one by one from index 0 to 5 and then loop as much as you like.
  2. Pick a random element and slice it out up until the array is empty and then refresh your array from a back up. (be careful not to back up with a reference or your backup array gets deleted along with the one gets spliced. so use .slice())

Array.prototype.shuffle = function(){
  var a = this.slice(), // don't morph the original
      i = a.length,
      j;
  while (i > 1) {
    j = ~~(Math.random()*i--);
    a[i] = [a[j],a[j]=a[i]][0];
  }
return a;
};

var album = ["photo1","photo2","photo3","photo4","photo5"];
photos = album.shuffle();
photos.forEach(p => console.log(p));

console.log("another way") // the splice way

photos = album.slice();
while (photos.length) console.log(photos.splice(Math.floor(Math.random() * photos.length),1)[0]);
!photos.length && (photos = album.slice()); // restore photos album and continue
while (photos.length) console.log(photos.splice(Math.floor(Math.random() * photos.length),1)[0]);
!photos.length && (photos = album.slice()); // restore photos album and continue
Redu
  • 25,060
  • 6
  • 56
  • 76
0

Following @Redu and my comments, take it out after you use it, but work on a copy.

var animations = ['fadeIn', 'fadeInDown', 'slideInUp', 'flipInY', 'bounceInLeft'];
var j;
var tmp = animations.slice(); //copy

var removed = 0;
for (var i = 1; i < 20; i++) {
    j = Math.floor(Math.random() * tmp.length);
    console.log(tmp[j]);
    tmp.splice(j, 1);
    removed++;
    if (animations.length == removed) {
        tmp = animations.slice();
        removed = 0
    }
}
Jeremy Kahan
  • 3,796
  • 1
  • 10
  • 23
  • what does the `remove` do? – Maria Jane Sep 18 '16 at 14:56
  • and animations.slice() returned the same value as animations. What's the slice() for then? – Maria Jane Sep 18 '16 at 14:58
  • removed counts how many items were removed from tmp. When all of them have been removed, we need to reset tmp to be all the animations and start over. animations.slice does return the same value as animations, but it is a copy, which does not mess with the original array, which is useful both if you want to use it elsewhere and when I want to reset tmp and do not want to have lost what to reset it to. – Jeremy Kahan Sep 18 '16 at 15:12
  • it's easy to put everything in a loop. In my case it has to be within a user's click event. – Maria Jane Sep 18 '16 at 15:19
  • what I wrote is in a loop? I was just illustrating what 19 runs would look like. You can adapt for your own loop. – Jeremy Kahan Sep 18 '16 at 15:27
0

I suggest to use a different method, by storing the last two selected elements and choose a different from the last selected items.

That prevent slicing and manipulation of original array.

function Random(array) {
    var last = [];
    this.next = function () {
        var r;
        do {
            r = Math.floor(Math.random() * array.length);
        } while (~last.indexOf(r))
        last.length === 2 && last.shift();
        last.push(r);
        return array[r];
    }
}

var animations = ['fadeIn', 'fadeInDown', 'slideInUp', 'flipInY', 'bounceInLeft'],
    random = new Random(animations),
    i;

for (i = 0; i < 15; i++) {
    console.log(random.next());
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392