-1

I am trying to get some HTML dom elements remotely from some website with jquery/javascript. These elements are in the array and unique, but when I try to print them with math.random() * my array.length i see duplicates. I want imgIdx to be unique.

So for the sake of helping me learn, can someone help me determine what am I missing here?

myarray = [
{ thumb : "http://url.com/img1.jpg", big : "http://url.com/img51.jpg" },
{ thumb : "http://url.com/img61.jpg", big : "http://url.com/img671.jpg" },
{ thumb : "http://url.com/img666.jpg", big : "http://url.com/img371.jpg" },]

function addSomeImages(limit) {
    for (var i = lastIdx; i < lastIdx + limit; i++) {
        var imgIdx = Math.floor(Math.random() * myarray.length);
        $('#endless-gallery').append('<a data-fancybox="gallery" href="' + myarray[imgIdx].big + '">' + '<img class=photo src="' + myarray[imgIdx].thumb + '' +
            '" />' +
            '</a>');
    }
Iman Bahrampour
  • 6,180
  • 2
  • 41
  • 64

1 Answers1

0

What's important to note that hasn't been touched from what I've noticed is why exactly your current solution isn't working, or why shuffling your array is the ideal approach. What you need to realize is that your current code is just generating a random index for you to use to access elements in your array. Much like rolling a die, it's much more likely that you'll re-roll a number than you are to roll each of the numbers without repeating. That's the entire point of (pseudo-)random number generation, that the results are effectively non-deterministic by nature.

With that in mind, in order to retrieve elements from your array randomly without repeating, you will have to find a way to exclude repeats by design. The two most practical ways to do this are to either:

1) Shuffle the array and simply iterate through it as noted in the comments on your question, or

2) Remove the accessed elements from your array and loop until the array is empty.

Of the above two, simply shuffling the array is far more practical and doesn't result in the destruction of your array (or require cloning the array and destroying the clone), so it's easily the ideal solution for you to use.

Why these work while your original solution doesn't:

Shuffling the array is a procedure by which your array contains the same exact elements as it originally contains, but are simply ordered randomly in the array. Much like the name implies, it's like shuffling a deck of cards; you'll always have your standard 52 unique cards, but they'll just be in a different order. As you flip through the shuffled cards, there's no risk of somehow coming across the same card that you've already passed.

Removing an element and looping until empty is like taking a perfectly-sorted deck of 52 unique cards and pulling a random one out from the deck repeatedly, discarding the ones you've already pulled out. If the card you pull out is no longer in the deck, you'll never be at risk of pulling the same card out.

What you're doing right now taking that perfectly-sorted deck of 52 cards, looking at a random one, and placing it back where it was in the deck before repeating the process. The card is still there, and because you're just looking at random cards it's possible for you to inadvertently look at it a second time.

Since shuffling the array and then iterating through the results normally is the ideal approach, consider using the Fisher-Yates shuffle function noted in the comments:

function shuffle(array) {
    var currentIndex = array.length, temporaryValue, randomIndex;

    // While there remain elements to shuffle...
    while (0 !== currentIndex) {

        // Pick a remaining element...
        randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex -= 1;

        // And swap it with the current element.
        temporaryValue = array[currentIndex];
        array[currentIndex] = array[randomIndex];
        array[randomIndex] = temporaryValue;
    }

    return array;
}

Then you can do something like:

myarray = [ ... ];
myarray = shuffle(myarray);

function addSomeImages(limit) {
    //note: ensure that "lastIdx + limit <= myarray.length" or you could exceed the array bounds!
    for (var i = lastIdx; i < lastIdx + limit; i++) {
        $('#endless-gallery').append('<a data-fancybox="gallery" href="' + myarray[i].big + '"><img class="photo" src="' + myarray[i].thumb + '" /></a>');
    }
}
B. Fleming
  • 7,170
  • 1
  • 18
  • 36