SitePoint Sponsor

User Tag List

Results 1 to 13 of 13
  1. #1
    SitePoint Member
    Join Date
    Jun 2010
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Random Image with No Repeats

    I've got an array of images that I want to randomly attach themselves in some <li> tags. Right now I've got everything working great except the images repeat sometimes repeat themselves.

    Is there any way to make the images not repeat?

    Here's the code:

    Code JavaScript:
    // Random Image
     
    var theImages = new Array() 
     
    theImages[0] = 'images/newsalerts/courtroom.jpg"'
    theImages[1] = 'images/newsalerts/officer.jpg"'
    theImages[2] = 'images/newsalerts/police_dispatcher.jpg"'
    theImages[3] = 'images/newsalerts/prison_fence.jpg"'
    theImages[4] = 'images/newsalerts/standing_by_car.jpg"'
    theImages[5] = 'images/newsalerts/computer_keyboard.jpg"'
    theImages[6] = 'images/newsalerts/counselor_inmate.jpg"'
    theImages[7] = 'images/newsalerts/crime_scene.jpg"'
    theImages[8] = 'images/newsalerts/police_cruiser.jpg"'
     
    var p = theImages.length;
    var preBuffer = new Array()
    for (i = 0; i < p; i++){
       preBuffer[i] = new Image()
       preBuffer[i].src = theImages[i]
    }
     
    //Activate Immediately
    $(document).ready(function(){
     
    	//Runs Script each time there is an <li>
    	$("#news li").each(function(){		
     
    		//Generates the Image						
    		var whichImage = Math.round(Math.random()*(p-1));
     
    		//Puts Image in front of everything in <li>
    		$(this).prepend('<img src="'+theImages[whichImage]+'">');
     
    	});
     
    });

    Any help would be appreciated. I hope I have made it clear, If not let me know and I'll try to explain a little more.

    Thanks!

  2. #2
    ♪♪ ♪ ♪ ♪ ♪♪ ♪ ♪♪ Markdidj's Avatar
    Join Date
    Sep 2002
    Location
    Bournemouth, South UK
    Posts
    1,551
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    You could create another array, and check against that, but the way I like to do it is with a string containing a letter to represent each image. Take the nth letter, and remove it from the string by replacing with ""
    LiveScript: Putting the "Live" Back into JavaScript
    if live output_as_javascript else output_as_html end if

  3. #3
    SitePoint Guru
    Join Date
    Apr 2006
    Posts
    802
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Shuffle the array before you start, and take them in the shuffled order.
    ...
    theImages[8] = 'images/newsalerts/police_cruiser.jpg"';
    theImages.sort(function(){return Math.random-.5});

  4. #4
    SitePoint Member
    Join Date
    Jun 2010
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Shuffle the array before you start, and take them in the shuffled order.
    ...
    theImages[8] = 'images/newsalerts/police_cruiser.jpg"';
    theImages.sort(function(){return Math.random-.5});
    mrhoo - this makes perfect sense but i'm having trouble outputting the images. what do i write to make the images appear?

    At this point I have:

    Code JavaScript:
    var whichImage = Math.round(Math.random()*(p-1));

    which now they don't need to be random anymore?

    Any help would be appreciated!

  5. #5
    SitePoint Evangelist
    Join Date
    Jul 2007
    Posts
    345
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mrhoo View Post
    Shuffle the array before you start, and take them in the shuffled order.
    ...
    theImages[8] = 'images/newsalerts/police_cruiser.jpg"';
    theImages.sort(function(){return Math.random-.5});
    While that method will shuffle the array, it doesn't produce a uniform distribution. i.e. some images will be more likely to appear at the start of the array than others.

    To shuffle the array, try
    Code:
    var shuffled = [];
    
    while (theImages.length) {
    	shuffled.push(theImages.splice(Math.random() * theImages.length, 1));
    }
    Then assign the src using an index in the jQuery each loop
    Code:
    //Activate Immediately
    $(document).ready(function(){
        
        //Runs Script each time there is an <li>
        $("#news li").each(function(index){    
            
            //Puts Image in front of everything in <li>
            $(this).prepend('<img src="'+shuffled[index]+'">');
            
        });
        
    });

  6. #6
    SitePoint Member
    Join Date
    Jun 2010
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That works GREAT!!! Thank you so much.

    If you have a couple of mins do you mind explaining what's going on here?

    I have the basic knowledge of what's happening but don't know the specifics.

    Thanks again

  7. #7
    SitePoint Evangelist
    Join Date
    Jul 2007
    Posts
    345
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Code:
    // Create an array to hold the shuffled images
    var shuffled = [];
    
    // Keep removing one image at random from theImages
    // placing it in the shuffled array
    // until theImages is empty
    while (theImages.length) {
    	shuffled.push(theImages.splice(Math.random() * theImages.length, 1));
    }
    The splice array method is being used to remove and return a single element from theImages.
    Code:
    // remove one image from the start of the array
    // i.e. remove the first image
    var removed = theImages.splice(0, 1);
    
    // remove one image from index 3 in the array
    // i.e. remove the fourth image
    var removedToo = theImages.splice(3, 1);
    Which element to remove is being chosen at random. The index must be from 0 to one less than the length of the array. The random index generated will be a decimal, but only the integer part is used.
    Code:
    // remove one image from a random position in the array
    var randomImage = theImages.splice(Math.random() * theImages.length, 1);
    
    // add the removed image to the shuffled array
    shuffled.push(randomImage);
    
    // or remove from original and add to shuffled in one go
    shuffled.push(theImages.splice(Math.random() * theImages.length, 1));
    As images are removed from theImages array, its length decreases one by one until it reaches zero. At that point, the while condition will be treated as false and the shuffled array will be ready.
    Code:
    while (theImages.length) {
      // will be executed if theImages still has images in it
      // i.e. its length is greater than zero
    }

  8. #8
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,815
    Mentioned
    25 Post(s)
    Tagged
    1 Thread(s)
    theImages.sort(function(){return Math.random-.5});

    should be completely random in the result. Any bias you get with your results simply means you didn't take a big enough sample.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  9. #9
    SitePoint Evangelist
    Join Date
    Jul 2007
    Posts
    345
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by felgall View Post
    theImages.sort(function(){return Math.random-.5});

    should be completely random in the result. Any bias you get with your results simply means you didn't take a big enough sample.
    What makes you so sure?

    While any two elements being compared will be swapped at random, the sort algorithm determines which elements will be compared.

  10. #10
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,815
    Mentioned
    25 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by r51 View Post
    What makes you so sure?
    Logically with the search algorithm that JavaScript uses I would have expected a completely random distribution.

    Since trying to explain how the particular sort algorithm would produce random results is somewhat complicated I decided that running a large test would be an easier way to demonstrate.

    JavaScript must not be using the sort algorithm I thought that it was because you are right - the distribution after a single sort isn't random. The test I did was an array of ten numbers in order zero through nine sorted a million times (starting over with them in order each time). The results did show a bias toward the existing order being maintained with elements staying close to their original position being about twice as likely as moving further away.

    Performing multiple sorts one after the other reduced the bias and sorting a table multiple times reduces the bias. Sorting a ten element table fifteen times appears to give fairly random results (I couldn't see any particular bias across multiple tests when I did that).

    If you only have a few items to sort then the bias isn't going to be all that great and you can reduce it by repeating the sort.

    The sort actually showed less bias with subtracting .25 instead of .5 and four sorts using .25 gave me more random results than fifteen sorts using .5. The results after running a million tests with four sorts subtracting .25 gave all the possibilities within a fraction of 1&#37; of each other and rerunning the test suite several times gave similar results with no obvious bias showing up between tests.

    So instead of

    theImages.sort(function(){return Math.random-.5});

    the following will give a far more random result:

    theImages.sort(function(){return Math.random-.25});
    theImages.sort(function(){return Math.random-.25});
    theImages.sort(function(){return Math.random-.25});
    theImages.sort(function(){return Math.random-.25});

    So creating your own sort code might just possibly be more efficient than running the inbuilt one four times.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  11. #11
    SitePoint Evangelist
    Join Date
    Jul 2007
    Posts
    345
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by felgall View Post
    Logically with the search algorithm that JavaScript uses I would have expected a completely random distribution.
    Logically, I wouldn't expect a uniform distribution!

    During a comparison of two elements, you originally set the probability of swapping them to one half. As sorting algorithms are simply a composition of many swaps, the final probability distribution will contain probabilities which are all sums of the reciprocals of powers of two. That makes it impossible to get a uniform distribution for many array lengths.

    True, fiddling with your comparison function and shaking the array many times may help, but the final distribution will still be dependent on the sorting algorithm.

    The algorithm given below picks each element at random, giving a uniform distribution. What's not to like?
    Code:
    var shuffled = [];
    
    while (theImages.length) {
    	shuffled.push(theImages.splice(Math.random() * theImages.length, 1));
    }

  12. #12
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,815
    Mentioned
    25 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by r51 View Post
    Logically, I wouldn't expect a uniform distribution!
    I wasn't expecting a uniform distribution, I was expecting that by running the test multiple times that I'd get different distributions each time with no obvious bias toward particular arrangements. Instead each test I ran that only sorted once while it gave different results each time did demonstrate a bias toward the elements staying closer to their original position. Changing the comparison reduced the bias.

    Quote Originally Posted by r51 View Post
    What's not to like?
    There is nothing to not like about your solution there since doing an insertion sort that way does guarantee that there should not be any bias in the result.

    I had expected that the sort algorithm JavaScript uses was one that would be similarly free of bias since there are a number of algorithms for sorting that do not display any bias however it appears that JavaScript does not use one of those algorithms.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  13. #13
    SitePoint Evangelist
    Join Date
    Jul 2007
    Posts
    345
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by felgall View Post
    ...with no obvious bias toward particular arrangements.
    That's what I mean by a uniform distribution.

    Quote Originally Posted by felgall View Post
    ...there are a number of algorithms for sorting that do not display any bias...
    I would have thought sorting was inherently biased.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •