24

How can I select the first 5 random elements

<ul>
    <li>First</li>
    <li>Second</li>
    <li>Third</li>
     ...
    <li>N</li>
</ul>

I'm using this plugin:

alert($("li:random").text());

but it takes all random elements. I only want the first 5.

Is there another way to do the same thing?

AlexC
  • 9,657
  • 17
  • 64
  • 98
  • Can you wrap a div around the first five server-side, then use li #first-five:random ? – Kzqai Nov 19 '09 at 15:39
  • I am not aware of jQuery supporting the ":random" pseudo-selector, how do you add this functionality and what's the code logic behind it ? – duckyflip Nov 19 '09 at 16:10
  • http://blog.mastykarz.nl/jquery-random-filter/ but if do You can show me another way, how to select 5 random element , will be awesome – AlexC Nov 19 '09 at 16:16

6 Answers6

52

Here's how to get 5 random elements from a jQuery selection, no need of plugins!

randomElements = jQuery("li").get().sort(function(){ 
  return Math.round(Math.random())-0.5
}).slice(0,5)

At this point you have 5 DomElements that have been selected randomly from all the LIs that jQuery returned

You can then do whatever you like with them,
e.g change their color:

$(randomElements).css("color","red")

or display their combined text contents:

$(randomElements).text()
duckyflip
  • 16,189
  • 5
  • 33
  • 36
  • +1, though I'm curious as to why you spelt "random" consistently correctly in the text, and consistently incorrectly in the code snippets... :-) – Andrzej Doyle Nov 19 '09 at 17:00
  • 3
    The general idea is good, but you shouldn't shuffle an array like that. Sorting is an inefficient way to shuffle an array, and an inconsistent comparison can cause problems (even potentially causing the sort to loop indefinitely). It's better to use a Fisher-Yates shuffle (http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle). – Matthew Crumley Nov 19 '09 at 18:07
  • 6
    That won't get you a randomly sorted array. Here's an article about it (it's Objective-C, but shouldn't matter) http://cocoawithlove.com/2010/06/sorting-nsmutablearray-with-random.html – Georg Schölly Jun 14 '10 at 09:22
  • As Georg pointed out, this will not produce a random set as at least one pivot element (most probably the one in the middle) will be used when (quick)sorting the array. Georg's link was a good read! Downvoting. – Alexander Wallin Jan 24 '11 at 13:58
  • 1
    This is bad. Selecting X random elements is `O(1)`, while sorting whole collection takes `O(n log n)` at best. – Rok Kralj Aug 06 '13 at 12:20
8

Get a random number index, 1-5, and get the child of the ul with that index. Like so:

var index = Math.floor(Math.random() * 5) + 1;  // nth-child indices start at 1
alert($("ul:nth-child(" + index + ")").text());
David Hu
  • 3,076
  • 24
  • 26
Frank DeRosa
  • 2,271
  • 2
  • 14
  • 12
  • 2
    Oh, this is completely wrong. I read the question as requesting one random element out of the first five, not five random elements from the set. I think I need sleep! :D – Frank DeRosa Nov 20 '09 at 03:24
  • 5
    Got here by searching exactly for this kind of solution. So answering to misread qestions is not always bad :) – Z. Zlatev May 11 '10 at 17:16
  • 1
    `Math.random()` [returns a value in [0,1)](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Math/random) -- that is, including 0 but excluding 1. So there's the possibility (albeit rare) that `index` will be `0`. To avoid this, use `var index = Math.floor(Math.random() * 5) + 1;`. – David Hu Dec 02 '11 at 01:13
8

Using the Fisher-Yates shuffle I have created a small script for this purpose. This is done by first creating a randomly shuffled and sliced copy of the array of jQuery elements, and then filtering out all elements that do not exist in both arrays.

You can read about it at http://www.afekenholm.se/jquery-rand. Here's the script:

/**
 * jQuery.rand v1.0
 * 
 * Randomly filters any number of elements from a jQuery set.
 * 
 * MIT License: @link http://www.afekenholm.se/license.txt
 * 
 * @author: Alexander Wallin (http://www.afekenholm.se)
 * @version: 1.0
 * @url: http://www.afekenholm.se/jquery-rand
 */
(function($){
    $.fn.rand = function(k){
        var b = this,
            n = b.size(),
            k = k ? parseInt(k) : 1;

        // Special cases
        if (k > n) return b.pushStack(b);
        else if (k == 1) return b.filter(":eq(" + Math.floor(Math.random()*n) + ")");

        // Create a randomized copy of the set of elements,
        // using Fisher-Yates sorting
        r = b.get();
        for (var i = 0; i < n - 1; i++) {
            var swap = Math.floor(Math.random() * (n - i)) + i;
            r[swap] = r.splice(i, 1, r[swap])[0];
        }
        r = r.slice(0, k);

        // Finally, filter jQuery stack
        return b.filter(function(i){
            return $.inArray(b.get(i), r) > -1;
        });
    };
})(jQuery);
Alexander Wallin
  • 1,394
  • 10
  • 22
2
  jQuery.jQueryRandom = 0;
  jQuery.extend(jQuery.expr[":"], {
    random: function(a, i, m, r) {
      if (i == 0) {
        jQuery.jQueryRandom = Math.floor(Math.random() * r.length);
      };
      return i == jQuery.jQueryRandom;
    }
  });
0
$("li:lt(5):random").text()
Nikolas Stephan
  • 1,280
  • 12
  • 10
-1

Why not just do this, it seems pretty efficient:

jQuery('li:random').slice(0, 5);
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313